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.

10713 lines
298 KiB

  1. # _____________________________________________________________________________
  2. #
  3. # Purpose:
  4. # PERL Module to handle common tasks for SDX
  5. #
  6. # Parameters:
  7. # Specific to subroutine
  8. #
  9. # Output:
  10. # Specific to subroutine
  11. #
  12. # _____________________________________________________________________________
  13. #
  14. # Some Global Definitions
  15. #
  16. $TRUE = 1;
  17. $FALSE = 0;
  18. $Callee = "";
  19. package SDX;
  20. require Win32::Mutex;
  21. # _____________________________________________________________________________
  22. #
  23. # Init
  24. #
  25. # Parameters:
  26. # Command Line Arguments
  27. #
  28. # Output:
  29. # _____________________________________________________________________________
  30. sub Init
  31. {
  32. #
  33. # Initialize globals
  34. #
  35. $main::Initializing = $main::TRUE;
  36. $main::CreatingBranch= $main::FALSE;
  37. $main::tmptmp = "$ENV{TMP}\\tmp";
  38. $main::Platform = $ENV{PROCESSOR_ARCHITECTURE};
  39. $main::StartPath = $ENV{STARTPATH};
  40. $main::CodeBaseType = 0; # 1 == one project/depot, 2 == N projects/depot
  41. $main::Null = "";
  42. @main::ActiveDepots = ();
  43. %main::DepotType = ();
  44. @main::SDMapProjects = ();
  45. @main::SDMapDepots = ();
  46. @main::AllMappings = ();
  47. @main::AllProjects = ();
  48. @main::AllGroups = ();
  49. @main::AllDepots = ();
  50. @main::FileChunks = ();
  51. $main::DepotFiles = 0;
  52. $main::SDMapClient = "";
  53. $main::SDMapBranch = "";
  54. $main::SDMapCodeBase = "";
  55. $main::SDMapCodeBaseType = "";
  56. $main::Log = "";
  57. $main::SDWeb = "http://sourcedepot";
  58. $main::Files = 0;
  59. $main::FilesResolved = 0;
  60. $main::FilesUpdated = 0;
  61. $main::FilesAdded = 0;
  62. $main::FilesDeleted = 0;
  63. $main::FilesToResolve = 0;
  64. $main::FilesToMerge = 0;
  65. $main::FilesNotClobbered = 0;
  66. $main::FilesOpenAdd = 0;
  67. $main::FilesOpenEdit = 0;
  68. $main::FilesOpenDelete = 0;
  69. $main::FilesReverted = 0;
  70. $main::FilesNotConflicting = 0;
  71. $main::FilesSkipped = 0;
  72. $main::FilesConflicting = 0;
  73. @main::ConflictingFiles = ();
  74. $main::Changes = 0;
  75. $main::IntegrationChanges = 0;
  76. $main::LabelFilesAdded = 0;
  77. $main::LabelFilesDeleted = 0;
  78. $main::LabelFilesUpdated = 0;
  79. $main::IntFilesAdded = 0;
  80. $main::IntFilesDeleted = 0;
  81. $main::IntFilesChanged = 0;
  82. $main::DepotErrors = 0;
  83. ### $main::FailedSubmits = 0;
  84. ### $main::FilesLocked = 0;
  85. $main::Mutex;
  86. $main::HaveMutex = $main::FALSE;
  87. %main::DepotsSeen = ();
  88. #
  89. # list of project names not to allow as aliases
  90. #
  91. %main::BadAliases =
  92. (
  93. alias => 1,
  94. build => 1,
  95. cat => 1,
  96. cmd => 1,
  97. cd => 1,
  98. cp => 1,
  99. dir => 1,
  100. du => 1,
  101. kill => 1,
  102. list => 1,
  103. ls => 1,
  104. mv => 1,
  105. net => 1,
  106. rm => 1,
  107. sd => 1,
  108. sdx => 1,
  109. setup => 1,
  110. tc => 1,
  111. vi => 1,
  112. where => 1,
  113. xcopy => 1
  114. );
  115. #
  116. # hash of arrays of files to give the user
  117. #
  118. %main::SDXTools = (
  119. toSDXRoot => [
  120. "alias.sdx",
  121. ],
  122. toSDTools => [
  123. "sdx.cmd",
  124. "sdx.pl",
  125. "sdx.pm"
  126. ],
  127. toSDToolsPA => [
  128. "alias.exe",
  129. "perl.exe",
  130. "perlcore.dll",
  131. "perlcrt.dll",
  132. "sd.exe",
  133. ],
  134. );
  135. #
  136. # hash of function pointers and default args
  137. #
  138. # command type 1 assumes the codebase type is 1 -- one project per depot
  139. #
  140. # if we find it's actually type 2 (N projects/depot), some of these will be
  141. # modified later to change the scope of the command, since some commands
  142. # (sd info, sd clients, sd branches) only make sense when reported per depot
  143. # and are redundant when reported per project
  144. #
  145. # OtherOp() uses cmd type to determine whether to loop through projects and
  146. # talk to depots by using SDPORT in SD.INI in each project root, or to
  147. # loop through the list of enlisted depots from SD.MAP
  148. #
  149. %main::SDCmds =
  150. ( # scope scope
  151. # # for type 1 for type 2
  152. # those that help with SDX # (1:1) codebases (N:1) codebases
  153. #
  154. commands => {fn => \&OtherOp, defcmd => "", defarg => "", type => 1,}, # n/a n/a
  155. usage => {fn => \&OtherOp, defcmd => "", defarg => "", type => 1,}, # n/a n/a
  156. #
  157. # those that change client or server state
  158. #
  159. client => {fn => \&OtherOp, defcmd => "client", defarg => "", type => 1,}, # project depot
  160. defect => {fn => \&Defect, defcmd => "", defarg => "", type => 1,}, # project depot
  161. deletefile => {fn => \&OtherOp, defcmd => "delete", defarg => "", type => 1,}, # project project
  162. editfile => {fn => \&OtherOp, defcmd => "edit", defarg => "", type => 1,}, # project project
  163. enlist => {fn => \&Enlist, defcmd => "", defarg => "", type => 1,}, # project depot
  164. flush => {fn => \&OtherOp, defcmd => "flush", defarg => "", type => 1,}, # project project
  165. integrate => {fn => \&OtherOp, defcmd => "integrate", defarg => "", type => 1,}, # project depot
  166. labbranch => {fn => \&OtherOp, defcmd => "lbranch", defarg => "", type => 1,}, # project depot
  167. label => {fn => \&OtherOp, defcmd => "label", defarg => "", type => 1,}, # project depot
  168. labelsync => {fn => \&OtherOp, defcmd => "labelsync", defarg => "", type => 1,}, # project depot
  169. protect => {fn => \&OtherOp, defcmd => "protect", defarg => "", type => 1,}, # project depot
  170. repair => {fn => \&Repair, defcmd => "", defarg => "", type => 1,}, # project depot
  171. resolve => {fn => \&OtherOp, defcmd => "resolve", defarg => "", type => 1,}, # project depot
  172. revert => {fn => \&OtherOp, defcmd => "revert", defarg => "", type => 1,}, # project depot
  173. submit => {fn => \&OtherOp, defcmd => "submit", defarg => "", type => 1,}, # project depot
  174. sync => {fn => \&OtherOp, defcmd => "sync", defarg => "", type => 1,}, # project project
  175. triggers => {fn => \&OtherOp, defcmd => "triggers", defarg => "", type => 1,}, # project depot
  176. #
  177. # those that report status
  178. #
  179. admin => {fn => \&OtherOp, defcmd => "admin", defarg => "", type => 1,}, # project depot
  180. # branch => {fn => \&OtherOp, defcmd => "branch", defarg => "", type => 1,}, # project depot
  181. branches => {fn => \&OtherOp, defcmd => "branches", defarg => "", type => 1,}, # project depot
  182. clients => {fn => \&OtherOp, defcmd => "clients", defarg => "", type => 1,}, # project depot
  183. # change => {fn => \&OtherOp, defcmd => "change", defarg => "", type => 1,}, # project project
  184. changes => {fn => \&Changes, defcmd => "changes", defarg => "", type => 1,}, # project project
  185. counters => {fn => \&OtherOp, defcmd => "counters", defarg => "", type => 1,}, # project depot
  186. delta => {fn => \&Delta, defcmd => "", defarg => "", type => 1,},
  187. diff => {fn => \&OtherOp, defcmd => "diff", defarg => "", type => 1,},
  188. diff2 => {fn => \&OtherOp, defcmd => "diff2", defarg => "", type => 1,},
  189. dirs => {fn => \&OtherOp, defcmd => "dirs", defarg => "", type => 1,}, # project depot
  190. files => {fn => \&OtherOp, defcmd => "files", defarg => "", type => 1,}, # project project
  191. have => {fn => \&OtherOp, defcmd => "have", defarg => "", type => 1,}, # project project
  192. info => {fn => \&OtherOp, defcmd => "info", defarg => "", type => 1,}, # project depot
  193. integrated => {fn => \&OtherOp, defcmd => "integrated", defarg => "", type => 1,}, # project depot
  194. labels => {fn => \&OtherOp, defcmd => "labels", defarg => "", type => 1,}, # project depot
  195. opened => {fn => \&OtherOp, defcmd => "opened", defarg => "", type => 1,}, # project project
  196. pending => {fn => \&OtherOp, defcmd => "changes", defarg => "-s pending", type => 1,}, # project depot
  197. projects => {fn => \&OtherOp, defcmd => "projects", defarg => "", type => 1,}, # project project
  198. resolved => {fn => \&OtherOp, defcmd => "resolved", defarg => "", type => 1,}, # project depot
  199. status => {fn => \&OtherOp, defcmd => "status", defarg => "", type => 1,}, # project project
  200. # user => {fn => \&OtherOp, defcmd => "user", defarg => "", type => 1,}, # project depot
  201. users => {fn => \&OtherOp, defcmd => "users", defarg => "", type => 1,}, # project depot
  202. where => {fn => \&OtherOp, defcmd => "where", defarg => "", type => 1,}, # project project
  203. #
  204. # internal
  205. #
  206. enumdepots => {fn => \&OtherOp, defcmd => "enumdepots", defarg => "", type => 1,}, # project project
  207. );
  208. #
  209. # list of SD command/flag combinations not to allow
  210. #
  211. %main::BadCmds =
  212. (
  213. #
  214. # -c makes no sense since change numbers aren't consistent across name space
  215. #
  216. -c => [
  217. "integrate",
  218. "revert",
  219. "submit"
  220. ],
  221. #
  222. # don't want any switches to sdx branch/change/user except -o
  223. #
  224. -d => [
  225. "branch",
  226. "change",
  227. "user"
  228. ],
  229. -f => [
  230. "branch",
  231. "change",
  232. "user"
  233. ],
  234. #
  235. # don't want to branch/client/changelist/label/user spec changing with -i
  236. # sd(x) client is ok
  237. #
  238. -i => [
  239. "branch",
  240. "change",
  241. "client",
  242. "submit",
  243. "user"
  244. ],
  245. -t => [
  246. "client",
  247. "label"
  248. ],
  249. );
  250. #
  251. # set the starting dir
  252. #
  253. open(CWD, 'cd 2>&1|');
  254. $main::StartDir = <CWD>;
  255. close(CWD);
  256. chop $main::StartDir;
  257. #
  258. # figure out where we're running from
  259. #
  260. $main::InstallFrom = $ENV{STARTPATH};
  261. #
  262. # parse cmd line
  263. #
  264. SDX::ParseArgs(@_);
  265. #
  266. # return if we need usage already
  267. #
  268. $main::Usage and return;
  269. #
  270. # on new enlists in NT, don't let SDXROOT be > 8.3
  271. #
  272. # BUGBUG-1999/12/01-jeffmcd -- this should be an option in the codebase map -- SHORTROOT = 1
  273. #
  274. ($main::NewEnlist and "\U$main::CodeBase" eq "NT") and do
  275. {
  276. my $root = (split(/\\/, $main::SDXRoot))[1];
  277. (length((split/\./, $root)[0]) > 8 or length((split/\./, $root)[1]) > 3) and die("Please use an 8.3 name for \%SDXROOT\%.\n");
  278. };
  279. #
  280. # does the SD client exist?
  281. #
  282. grep(/ recognized /, `sd.exe 2>&1`) and die("\nCan't find Source Depot client SD.EXE.\n");
  283. #
  284. # SD.MAP contains the relative paths to the roots of all projects the user
  285. # is enlisted in, as created by SDX ENLIST, plus some keywords
  286. #
  287. # if we're doing anything other than enlisting or repairing, this must exist
  288. #
  289. $main::SDMap = "$main::SDXRoot\\sd.map";
  290. #
  291. # get attributes for this enlistment from SD.MAP
  292. #
  293. # fatal error if defecting, incrementally enlisting, or other op
  294. # error text comes from ReadSDMap()
  295. #
  296. $main::Enlisting and $op = "enlist";
  297. $main::Repairing and $op = "repair";
  298. $main::Defecting and $op = "defect";
  299. $main::OtherOp and $op = "otherop";
  300. my $rc = SDX::ReadSDMap($op, "init");
  301. !$rc and ($main::IncrEnlist or $main::Defecting or $main::OtherOp) and die("\n");
  302. #
  303. # if we have codebase and branch values from SD.MAP, use them
  304. #
  305. # handle some special cases
  306. #
  307. ($main::SDMapCodeBase and $main::SDMapBranch and $main::SDMapCodeBaseType) and do
  308. {
  309. #
  310. # on repair, warn the user we're changing these values
  311. #
  312. ($main::Repairing and $main::CodeBase and $main::Branch) and do
  313. {
  314. print "\nUsing codebase and branch from $main::SDMap for repair. Ignoring ";
  315. printf "%s.\n", $main::EnlistFromProfile ? "profile\n$main::Profile" : "'$main::CodeBase $main::Branch'\non command line";
  316. };
  317. #
  318. # if the user is trying to enlist using a profile, they're already enlisted.
  319. # the profile may have different codebase, branch or projects than what they
  320. # already have, so error out
  321. #
  322. # $main::EnlistFromProfile can also be set during a repair
  323. #
  324. ($main::EnlistFromProfile and !$main::Repairing) and do
  325. {
  326. print "\nEnlisting by profile is only supported for new enlistments.\n";
  327. $main::CodeBase = "";
  328. $main::Branch = "";
  329. $main::Usage = $main::TRUE;
  330. return;
  331. };
  332. #
  333. # this may look like a new enlist but is actually incremental
  334. #
  335. # this prevents us from generating a unique client name later on,
  336. # since the user is just adding another project to their enlistment
  337. # and thought they needed to specify cb/br on the cmd line
  338. #
  339. # also prevents enlisting a different codebase or branch in
  340. # this particular SDX Root
  341. #
  342. # repair-from-profile will also have $main::NewEnlist set
  343. #
  344. ($main::NewEnlist and !$main::Repairing) and do
  345. {
  346. print "\nUsing codebase and branch from $main::SDMap. Ignoring '$main::CodeBase $main::Branch'\n";
  347. print "on command line.\n";
  348. $main::NewEnlist = $main::FALSE;
  349. $main::IncrEnlist = $main::TRUE;
  350. };
  351. #
  352. # finally, set primary codebase, type and branch
  353. #
  354. $main::CodeBase = $main::SDMapCodeBase;
  355. $main::CodeBaseType = $main::SDMapCodeBaseType;
  356. $main::Branch = $main::SDMapBranch;
  357. };
  358. #
  359. # at this point we must have codebase, type and branch
  360. #
  361. (!$main::CodeBase or !$main::Branch) and do
  362. {
  363. print "\nMissing codebase and/or branch.\n";
  364. $main::Usage = $main::TRUE;
  365. return;
  366. };
  367. #
  368. # be NT-centric for a minute and see if we know
  369. # about a public change number
  370. #
  371. $main::PublicChangeNum = SDX::GetPublicChangeNum();
  372. #
  373. # if we're working in a type 2 (N projects per depot), modify some
  374. # commands to work per-depot instead of per-project
  375. #
  376. # ie sdx submit on a type 1 should work per-project (which is actually a depot) and
  377. # sdx submit on a type 2 should work per-depot (which encompasses several projects)
  378. #
  379. $main::CodeBaseType == 2 and do
  380. {
  381. $main::SDCmds{admin}{type} = 2;
  382. # $main::SDCmds{branch}{type} = 2;
  383. $main::SDCmds{branches}{type} = 2;
  384. $main::SDCmds{client}{type} = 2;
  385. $main::SDCmds{clients}{type} = 2;
  386. $main::SDCmds{counters}{type} = 2;
  387. $main::SDCmds{dirs}{type} = 2;
  388. $main::SDCmds{info}{type} = 2;
  389. $main::SDCmds{integrate}{type} = 2;
  390. $main::SDCmds{labbranch}{type} = 2;
  391. $main::SDCmds{label}{type} = 2;
  392. $main::SDCmds{labels}{type} = 2;
  393. $main::SDCmds{labelsync}{type} = 2;
  394. $main::SDCmds{pending}{type} = 2;
  395. $main::SDCmds{privatebranch}{type} = 2;
  396. $main::SDCmds{protect}{type} = 2;
  397. $main::SDCmds{submit}{type} = 2;
  398. $main::SDCmds{triggers}{type} = 2;
  399. $main::SDCmds{users}{type} = 2;
  400. #
  401. # these need to stay type 1 b/c they can take a filespec,
  402. # which doesn't make sense when executing per-depot
  403. # since we never leave %SDXROOT%
  404. #
  405. # $main::SDCmds{integrated}{type} = 2;
  406. # $main::SDCmds{resolve}{type} = 2;
  407. # $main::SDCmds{resolved}{type} = 2;
  408. };
  409. #
  410. # fatal if no codebase type and not enlisting clean
  411. #
  412. # on a clean enlist we won't know the type until we have a chance to read $main::CodeBaseMap
  413. #
  414. (!$main::NewEnlist and !$main::Repairing and !$main::CodeBaseType) and die("\nCan't determine codebase type. Please contact the SDX alias.\n");
  415. #
  416. # set SDUSER and SDCLIENT
  417. #
  418. # if SDUSER is already defined in the environment
  419. # assume it includes the domain name, and extract the user name
  420. # otherwise use %USERNAME% and %USERDOMAIN%
  421. #
  422. # if SDCLIENT is already defined, use it, otherwise default to %COMPUTERNAME%.
  423. #
  424. # when defecting or repairing, if SDCLIENT is defined in the env, use it,
  425. # otherwise use main::SDMapClient from SD.MAP. Ignore %COMPUTERNAME% unless we
  426. # have no other choice
  427. #
  428. $main::SDUser = $ENV{SDUSER};
  429. if ($main::SDUser)
  430. {
  431. $main::SDDomainUser = $main::SDUser;
  432. $main::SDUser = (split(/\\/, $main::SDDomainUser))[1];
  433. }
  434. else
  435. {
  436. $main::SDUser = $ENV{USERNAME};
  437. $main::SDDomainUser = "$ENV{USERDOMAIN}\\$main::SDUser";
  438. }
  439. #
  440. # domain can't be computername, that is, user must be logged into the domain
  441. #
  442. ("\U$ENV{USERDOMAIN}" eq "\U$ENV{COMPUTERNAME}") and die("\nTo enlist you must be logged into the domain and not your local machine.\n");
  443. $main::SDClient = $ENV{SDCLIENT};
  444. (!$main::SDClient) and do
  445. {
  446. $main::SDClient = ($main::Defecting or $main::Repairing or $main::IncrEnlist) ? $main::SDMapClient : $ENV{COMPUTERNAME};
  447. #
  448. # we may not be able to get the client name from SD.MAP so assume it's
  449. # just the computer name, we'll catch it later if it isn't
  450. #
  451. $main::Repairing and !$main::SDClient and do
  452. {
  453. print "\nResorting to \%COMPUTERNAME\% for SD client name. Please verify below that\n";
  454. print "this is the correct client for this enlistment before continuing. If not, set\n";
  455. print "\%SDCLIENT\% correctly at the command line and rerun this command.\n";
  456. $main::SDClient = $ENV{COMPUTERNAME};
  457. };
  458. };
  459. !$main::SDUser and die("\nCan't determine SD user name. Verify that %USERNAME% is set in\nthe environment.\n");
  460. !$main::SDClient and die("\nCan't determine SD client name. Verify that %COMPUTERNAME% is set\nin the environment.\n");
  461. $main::V3 and do
  462. {
  463. printf "init: startdir=%s\n", $main::StartDir;
  464. printf "init: startpath=%s\n", $main::StartPath;
  465. printf "init: sdr = '%s'\n", $main::SDXRoot;
  466. printf "init: sdm = '%s'\n", $main::SDMap;
  467. printf "init: sdc = '%s'\n", $main::SDClient;
  468. printf "init: sdu = '%s'\n", $main::SDUser;
  469. printf "init: sddu = '%s'\n", $main::SDDomainUser;
  470. printf "init: usage=%s\n", $main::Usage;
  471. };
  472. $main::Initializing = $main::FALSE;
  473. }
  474. # _____________________________________________________________________________
  475. #
  476. # Parses command line arguments to verify the right syntax is being used
  477. #
  478. # Parameters:
  479. # Command Line Arguments
  480. #
  481. # Output:
  482. # Errors if the wrong syntax is used otherwise sets the appropriate variables
  483. # based on the command line arguments
  484. # _____________________________________________________________________________
  485. sub ParseArgs
  486. {
  487. #
  488. # Initialize variables
  489. #
  490. $ArgCounter = 1; # start at one since 0th arg is redundant
  491. $main::Usage = $main::FALSE;
  492. $main::GetStarted = $main::TRUE;
  493. $main::V1 = $main::FALSE;
  494. $main::V2 = $main::FALSE;
  495. $main::V3 = $main::FALSE;
  496. $main::Enlisting = $main::FALSE;
  497. $main::Defecting = $main::FALSE;
  498. $main::Repairing = $main::FALSE;
  499. $main::OtherOp = $main::TRUE;
  500. $main::EnlistAll = $main::FALSE;
  501. $main::EnlistClean = $main::FALSE;
  502. $main::EnlistGroup = $main::FALSE;
  503. $main::EnlistSome = $main::FALSE;
  504. $main::EnlistFromProfile = $main::FALSE;
  505. $main::NewEnlist = $main::FALSE;
  506. $main::IncrEnlist = $main::FALSE;
  507. $main::Exclusions = $main::TRUE;
  508. $main::RestrictRoot = $main::FALSE;
  509. $main::EnlistAsOther = $main::FALSE;
  510. $main::Sync = $main::FALSE;
  511. $main::DefectWithPrejudice = $main::FALSE;
  512. $main::ToolsInRoot = $main::FALSE;
  513. $main::Quiet = $main::FALSE;
  514. $main::Logging = $main::FALSE;
  515. $main::CBMProjectField = 0; # change these if you change
  516. $main::CBMGroupField = 1; # the ordering of fields in
  517. $main::CBMServerPortField = 2; # file PROJECTS.<CODEBASE>
  518. $main::CBMDepotNameField = 3;
  519. $main::CBMProjectRootField = 4;
  520. $main::Profile = "";
  521. $main::OtherClient = "";
  522. $main::UserArgs = " ";
  523. $main::Branch = "";
  524. $main::SDXRoot = "";
  525. $main::SDCmd = "";
  526. $main::CodeBase = "";
  527. $main::SubmitComment = "";
  528. $main::ToolsProject = "";
  529. $main::ToolsPath = "";
  530. $main::ToolsProjectPath = "";
  531. @main::OtherDirs = ();
  532. @main::DefaultProjects = ();
  533. @main::PlatformProjects = ();
  534. @main::SomeProjects = ();
  535. @main::ProfileProjects = ();
  536. @main::InputForm = ();
  537. $main::MinusB = $main::FALSE;
  538. $main::MinusH = $main::FALSE;
  539. $main::MinusI = $main::FALSE;
  540. $main::MinusT = $main::FALSE;
  541. $main::MinusO = $main::FALSE;
  542. $main::MinusR = $main::FALSE;
  543. $main::MinusV = $main::FALSE;
  544. $main::MinusA = $main::FALSE;
  545. my $MinusC = $main::FALSE;
  546. my $MinusP = $main::FALSE;
  547. my $MinusX = $main::FALSE;
  548. #
  549. # check SDXROOT for correctness
  550. #
  551. !exists($ENV{SDXROOT}) and do
  552. {
  553. print "\n%SDXROOT% is not set.\n";
  554. $main::Usage = $main::TRUE;
  555. };
  556. #
  557. # don't allow illegal characters, or spaces at the beginning or end
  558. #
  559. # also don't allow '+' for now
  560. #
  561. my $root = $ENV{SDXROOT};
  562. (!$main::Usage and ($root =~ /[\/*?"<>|+]/ or $root =~ /[\t\s]+$/ or $root =~ /^[\t\s]+/)) and do
  563. {
  564. print "\n\%SDXROOT% contains bad or undesirable characters: '$root'.\n";
  565. $main::Usage = $main::TRUE;
  566. };
  567. !$main::Usage and ((substr($root,0,1) !~ /[A-Za-z]/) or (substr($root,1,1) !~ /:/) or (substr($root,2,1) !~ /\\/)) and do
  568. {
  569. print "\n%SDXROOT% badly formed: '$root'.\n";
  570. $main::Usage = $main::TRUE;
  571. };
  572. #
  573. # may need to bail and show usage
  574. #
  575. $main::Usage and return;
  576. #
  577. # otherwise set the root
  578. #
  579. $main::SDXRoot = $root;
  580. #
  581. # first arg is always the operation we want to do
  582. #
  583. # make sure it's not a flag
  584. # make sure it's a known cmd
  585. #
  586. if (($_[$ArgCounter] =~ /^-/) or ($_[$ArgCounter] =~ /^\//))
  587. {
  588. print "\nMissing command.\n";
  589. $main::Usage = $main::TRUE;
  590. return;
  591. }
  592. $main::SDCmd = $_[$ArgCounter];
  593. $main::SDCmd =~ tr/A-Z/a-z/;
  594. $ArgCounter++;
  595. #
  596. # return if no command or command not in list
  597. #
  598. if (!$main::SDCmd)
  599. {
  600. $main::Usage = $main::TRUE;
  601. return;
  602. }
  603. (!exists($main::SDCmds{$main::SDCmd})) and die("\nUnknown command '$main::SDCmd'. Try sdx -? for info.\n");
  604. #
  605. # determine which SDX command this is
  606. #
  607. # an "other" operation is assumed by default
  608. #
  609. # maybe show command list or usage
  610. #
  611. # if enlist/defect/repair, set flags and satisfy required
  612. # arguments later
  613. #
  614. ($main::SDCmd =~ /usage/) and $main::Usage = $main::TRUE;
  615. ($main::SDCmd =~ /commands/) and do
  616. {
  617. $main::Usage = $main::TRUE;
  618. $main::GetStarted = $main::FALSE;
  619. };
  620. $main::Usage and return;
  621. #
  622. # we have a valid command so any usage needed from this point
  623. # will be specific to main::SDCmd
  624. #
  625. $main::GetStarted = $main::FALSE;
  626. #
  627. # set flags for enlist/defect/repair
  628. #
  629. $main::SDCmd =~ /enlist/ and do
  630. {
  631. $main::Enlisting = $main::TRUE;
  632. $main::IncrEnlist = $main::TRUE;
  633. $main::EnlistSome = $main::TRUE;
  634. $main::OtherOp = $main::FALSE;
  635. };
  636. $main::SDCmd =~ /defect/ and do
  637. {
  638. $main::Defecting = $main::TRUE;
  639. $main::DefectSome = $main::TRUE;
  640. $main::OtherOp = $main::FALSE;
  641. };
  642. $main::SDCmd =~ /repair/ and do
  643. {
  644. $main::Repairing = $main::TRUE;
  645. $main::OtherOp = $main::FALSE;
  646. };
  647. my $ignore = "";
  648. #
  649. # Cycle through parameters
  650. #
  651. my $arg = "";
  652. my $subarg = "";
  653. while ($_[$ArgCounter])
  654. {
  655. #
  656. # if '-' or '/' is the first character in the arg then it's a flag
  657. #
  658. $arg = $_[$ArgCounter];
  659. if (($arg =~ /^-/) or ($arg =~ /^\//))
  660. {
  661. $ArgPosition = 0;
  662. CASE: while ($SubArg = substr $_[$ArgCounter], ++$ArgPosition)
  663. {
  664. $main::V2 and do
  665. {
  666. printf "subarg = '%s'\n", $SubArg;
  667. };
  668. #
  669. # -# <string> equals $SubmitComment
  670. #
  671. if ($SubArg =~ /^\#/)
  672. {
  673. #
  674. # the comment is from # to the end of the cmd string
  675. #
  676. if ($main::SDCmd eq "submit")
  677. {
  678. my $ac = $ArgCounter + 1;
  679. while ($_[$ac])
  680. {
  681. $main::SubmitComment .= "$_[$ac] ";
  682. $_[$ac] = "";
  683. $ac++;
  684. }
  685. #
  686. # set this for later
  687. #
  688. $main::MinusI = $main::TRUE;
  689. }
  690. next CASE;
  691. }
  692. #
  693. # -1 is verbose debugging
  694. #
  695. if ($SubArg =~ /^1/)
  696. {
  697. $main::V1 = $main::TRUE;
  698. next CASE;
  699. }
  700. #
  701. # -2 is very verbose
  702. #
  703. if ($SubArg =~ /^2/)
  704. {
  705. $main::V2 = $main::TRUE;
  706. next CASE;
  707. }
  708. #
  709. # -3 you get the picture
  710. #
  711. if ($SubArg =~ /^3/)
  712. {
  713. $main::V3 = $main::TRUE;
  714. next CASE;
  715. }
  716. #
  717. # -a equals All
  718. #
  719. # if enlisting set a flag for later
  720. # if defecting set defect flags
  721. # else pass on to the SD command
  722. #
  723. if ($SubArg =~ /^a/i)
  724. {
  725. if ($main::Enlisting)
  726. {
  727. $MinusA = $main::TRUE;
  728. }
  729. else
  730. {
  731. if ($main::Defecting)
  732. {
  733. $main::DefectAll = $main::TRUE;
  734. $main::DefectGroup = $main::FALSE;
  735. $main::DefectSome = $main::FALSE;
  736. # null out list in case we collected some projects already
  737. @main::SomeProjects = ();
  738. }
  739. else
  740. {
  741. if ($main::SDCmd eq "users" or $main::SDCmd eq "files" or $main::SDCmd eq "clients")
  742. {
  743. $main::MinusA = $main::TRUE;
  744. }
  745. else
  746. {
  747. SDX::AddUserArg($_[$ArgCounter]);
  748. }
  749. }
  750. }
  751. next CASE;
  752. }
  753. #
  754. # -b is build number
  755. #
  756. if ($SubArg =~ /^b/i)
  757. {
  758. if ($main::SDCmd eq "changes")
  759. {
  760. $main::MinusB = $main::TRUE;
  761. $ArgCounter++;
  762. if (!($main::BuildNumber = $_[$ArgCounter]))
  763. {
  764. print "\nMissing build number.\n";
  765. $main::Usage = $main::TRUE;
  766. }
  767. else
  768. {
  769. $_[$ArgCounter] = "";
  770. }
  771. }
  772. else
  773. {
  774. SDX::AddUserArg($_[$ArgCounter]);
  775. }
  776. next CASE;
  777. }
  778. #
  779. # -c is enlist clean
  780. #
  781. # if enlisting, set a flag for later
  782. # else pass on to the SD command
  783. #
  784. if ($SubArg =~ /^c/i)
  785. {
  786. if ($main::Enlisting)
  787. {
  788. $MinusC = $main::TRUE;
  789. }
  790. else
  791. {
  792. SDX::AddUserArg($_[$ArgCounter]);
  793. }
  794. next CASE;
  795. }
  796. #
  797. # if defecting, -f equals DefectWithPrejudice
  798. # else pass on to SD
  799. #
  800. if ($SubArg =~ /^f/i)
  801. {
  802. if ($main::Defecting)
  803. {
  804. $main::DefectWithPrejudice = $main::TRUE;
  805. }
  806. else
  807. {
  808. SDX::AddUserArg($_[$ArgCounter]);
  809. }
  810. next CASE;
  811. }
  812. #
  813. # -g equals Logging
  814. # the log file must be the next arg
  815. #
  816. if ($SubArg =~ /^g/i)
  817. {
  818. $ArgCounter++;
  819. if (!($main::Log = $_[$ArgCounter]))
  820. {
  821. print "\nMissing log file.\n";
  822. $main::Usage = $main::TRUE;
  823. }
  824. if (substr($main::Log,0,1) =~ /[\/-]/)
  825. {
  826. $main::Log !~ /\?/ and print "\nLog name '$main::Log' appears to be a command switch.\n";
  827. $main::Log = "";
  828. $main::Usage = $main::TRUE;
  829. }
  830. #
  831. # if we have a good log, set a flag and null out arg so it
  832. # doesn't end up in user args
  833. #
  834. !$main::Usage and ($main::Logging = $main::TRUE and $_[$ArgCounter] = "");
  835. next CASE;
  836. }
  837. #
  838. # -h -- set flag for later, on sync/flush only
  839. #
  840. if ($SubArg =~ /^h/i)
  841. {
  842. ($main::SDCmd =~ /sync|flush/) and $main::MinusH = $main::TRUE;
  843. next CASE;
  844. }
  845. #
  846. # -i -- read input form from cmd line, or
  847. # show integration changes if cmd is sync or flush, or
  848. # only rewrite SD.INIs if repairing
  849. #
  850. if ($SubArg =~ /^i/i)
  851. {
  852. $main::MinusI = $main::TRUE;
  853. ($main::SDCmd ne "sync" and $main::SDCmd ne "flush" and $main::SDCmd ne "repair" and $main::SDCmd ne "resolve") and @main::InputForm = <STDIN>;
  854. SDX::AddUserArg($_[$ArgCounter]);
  855. next CASE;
  856. }
  857. #
  858. # when enlisting, -m equals $MinimalTools
  859. #
  860. if ($SubArg =~ /^m/i)
  861. {
  862. if ($main::Enlisting)
  863. {
  864. $main::MinimalTools = $main::TRUE;
  865. }
  866. else
  867. {
  868. SDX::AddUserArg($_[$ArgCounter]);
  869. }
  870. next CASE;
  871. }
  872. #
  873. # -o -- set flag for later
  874. #
  875. if ($SubArg =~ /^o/i)
  876. {
  877. $main::MinusO = $main::TRUE;
  878. SDX::AddUserArg($_[$ArgCounter]);
  879. next CASE;
  880. }
  881. #
  882. # when enlisting or repairing, -p means read from profile
  883. # next arg must be path to the profile file
  884. #
  885. if ($SubArg =~ /^p/i)
  886. {
  887. if ($main::Enlisting or $main::Repairing)
  888. {
  889. $MinusP = $main::TRUE;
  890. $ArgCounter++;
  891. if (!($main::Profile = $_[$ArgCounter]))
  892. {
  893. print "\nMissing profile.\n";
  894. $main::Usage = $main::TRUE;
  895. }
  896. else
  897. {
  898. #
  899. # if we have a good Profile, set flags and null out arg so it
  900. # doesn't end up in user args
  901. #
  902. if (SDX::ReadProfile())
  903. {
  904. #
  905. # set flag for enlist or repair
  906. #
  907. $main::EnlistFromProfile = $main::TRUE;
  908. $main::Enlisting and do
  909. {
  910. $main::NewEnlist = $main::TRUE;
  911. $main::IncrEnlist = $main::FALSE;
  912. };
  913. $_[$ArgCounter] = "";
  914. }
  915. else
  916. {
  917. die("\n");
  918. }
  919. }
  920. }
  921. next CASE;
  922. }
  923. #
  924. # -q equals Quiet
  925. #
  926. if ($SubArg =~ /^q/i)
  927. {
  928. if ($main::SDCmd ne "diff2")
  929. {
  930. $main::Quiet = $main::TRUE;
  931. }
  932. else
  933. {
  934. SDX::AddUserArg($_[$ArgCounter]);
  935. }
  936. next CASE;
  937. }
  938. #
  939. # -r equals RI when submitting
  940. #
  941. if ($SubArg =~ /^r/i)
  942. {
  943. if ($main::SDCmd eq "submit")
  944. {
  945. $main::MinusR = $main::TRUE;
  946. $main::MinusT and do
  947. {
  948. printf "Already have -n, ignoring -%s.\n", $SubArg;
  949. $main::MinusR = $main::FALSE;
  950. };
  951. }
  952. else
  953. {
  954. SDX::AddUserArg($_[$ArgCounter]);
  955. }
  956. next CASE;
  957. }
  958. #
  959. # when enlisting, defecting or repairing, -s equals $Sync
  960. # else pass on
  961. #
  962. if ($SubArg =~ /^s/i)
  963. {
  964. if ($main::Enlisting || $main::Repairing || $main::Defecting)
  965. {
  966. $main::Sync = $main::TRUE;
  967. }
  968. else
  969. {
  970. SDX::AddUserArg($_[$ArgCounter]);
  971. }
  972. next CASE;
  973. }
  974. #
  975. # -t equals Integration when submitting
  976. #
  977. if ($SubArg =~ /^t/i)
  978. {
  979. if ($main::SDCmd eq "submit")
  980. {
  981. $main::MinusT = $main::TRUE;
  982. $main::MinusR and do
  983. {
  984. printf "Already have -r, ignoring -%s.\n", $SubArg;
  985. $main::MinusT = $main::FALSE;
  986. };
  987. }
  988. else
  989. {
  990. SDX::AddUserArg($_[$ArgCounter]);
  991. }
  992. next CASE;
  993. }
  994. #
  995. # -v equals Verbose
  996. #
  997. if ($SubArg =~ /^v/i)
  998. {
  999. $main::MinusV = $main::TRUE;
  1000. #
  1001. # maybe pass -v on to SD
  1002. #
  1003. ($main::SDCmd eq "integrate" or $main::SDCmd eq "resolve") and do
  1004. {
  1005. SDX::AddUserArg($_[$ArgCounter]);
  1006. };
  1007. next CASE;
  1008. }
  1009. #
  1010. # when enlisting, -x turns off $Exclusions
  1011. # else pass on to SD
  1012. #
  1013. if ($SubArg =~ /^x/)
  1014. {
  1015. if ($main::Enlisting)
  1016. {
  1017. $MinusX = $main::TRUE;
  1018. }
  1019. else
  1020. {
  1021. SDX::AddUserArg($_[$ArgCounter]);
  1022. }
  1023. next CASE;
  1024. }
  1025. #
  1026. # -h or -? equals $Usage
  1027. #
  1028. if (($SubArg =~ /^h/i) or ($SubArg =~ /^\?/))
  1029. {
  1030. $main::Usage = $main::TRUE;
  1031. last CASE;
  1032. }
  1033. #
  1034. # add the switch to the user arg list
  1035. #
  1036. SDX::AddUserArg($_[$ArgCounter]);
  1037. last CASE;
  1038. }
  1039. }
  1040. else
  1041. {
  1042. #
  1043. # process non-switch args
  1044. #
  1045. #
  1046. # for general SD commands, add the arg to the user arg list
  1047. #
  1048. $main::OtherOp and do
  1049. {
  1050. SDX::AddUserArg($_[$ArgCounter]);
  1051. };
  1052. #
  1053. # if enlisting, arg is one of
  1054. # @client
  1055. # codebase and branch pair
  1056. # project name
  1057. #
  1058. $main::Enlisting and do
  1059. {
  1060. #
  1061. # first look for @<client>
  1062. #
  1063. if ((substr($_[$ArgCounter],0,1) =~ /@/) and !$main::EnlistAsOther)
  1064. {
  1065. $main::EnlistAsOther = $main::TRUE;
  1066. $main::NewEnlist = $main::TRUE;
  1067. $main::IncrEnlist = $main::FALSE;
  1068. $main::EnlistSome = $main::FALSE;
  1069. $main::OtherClient = substr($_[$ArgCounter],1,length($_[$ArgCounter]));
  1070. !$main::OtherClient and do
  1071. {
  1072. print "\nMissing client name after '\@'.\n";
  1073. $main::Usage = $main::TRUE;
  1074. };
  1075. $main::V2 and do
  1076. {
  1077. print "\nenlist as other = $main::EnlistAsOther\n";
  1078. print "other = '$main::OtherClient'\n";
  1079. print "new enlist = $main::NewEnlist\n";
  1080. print "incr enlist = $main::IncrEnlist\n";
  1081. };
  1082. }
  1083. else
  1084. {
  1085. #
  1086. # test for codebase if we don't have it already
  1087. #
  1088. # if arg is a codebase name (of the form PROJECTS.<codebase>) this is a new enlist
  1089. # assume the arg following is the branch name
  1090. #
  1091. if (!$main::CodeBase and SDX::VerifyCBMap($_[$ArgCounter]))
  1092. {
  1093. $main::NewEnlist = $main::TRUE;
  1094. $main::IncrEnlist = $main::FALSE;
  1095. $main::CodeBase = $_[$ArgCounter++];
  1096. $main::Branch = $_[$ArgCounter];
  1097. if ($main::Usage = SDX::VerifyCodeBaseAndBranch($main::CodeBase, $main::Branch))
  1098. {
  1099. $main::CodeBase = "";
  1100. $main::Branch = "";
  1101. }
  1102. $main::V2 and do
  1103. {
  1104. print "\nnew enlist = $main::NewEnlist\n";
  1105. print "incr enlist = $main::IncrEnlist\n";
  1106. print "codebase = '$main::CodeBase'\n";
  1107. print "branch = '$main::Branch'\n";
  1108. };
  1109. }
  1110. else
  1111. {
  1112. #
  1113. # arg is a project name
  1114. #
  1115. # maybe add to list
  1116. #
  1117. if (!$main::EnlistAll and !$main::EnlistAsOther and !$main::EnlistFromProfile)
  1118. {
  1119. #
  1120. # BUGBUG-2000/01/26-jeffmcd -- finish
  1121. #
  1122. # if arg is of the form project\path\path\path, break it apart
  1123. # and associate the path with the project so we can write it in the view later
  1124. # else
  1125. # it's just a project name
  1126. #
  1127. # if ($_[$ArgCounter] =~ /.+\\.+/)
  1128. # {
  1129. # my @fields = split(/\\/,$_[$ArgCounter]);
  1130. # my $project = @fields[0];
  1131. # push @main::SomeProjects, $project;
  1132. #
  1133. # shift @fields;
  1134. # my $subpath = "";
  1135. # foreach (@fields) { $subpath .= "$_\\"; }
  1136. # chop $subpath;
  1137. # print "'$subpath'\n";
  1138. # # load the hash -- use project as key
  1139. # push @$main::ProjectSubPaths{$project}, $subpath;
  1140. # }
  1141. # else
  1142. # {
  1143. push @main::SomeProjects, $_[$ArgCounter];
  1144. # }
  1145. }
  1146. }
  1147. }
  1148. };
  1149. #
  1150. # if incrementally defecting, arg is project to defect from
  1151. #
  1152. ($main::Defecting and !$main::DefectAll) and do
  1153. {
  1154. push @main::SomeProjects, $_[$ArgCounter];
  1155. };
  1156. #
  1157. # if repairing, current arg and the next are codebase and branch
  1158. #
  1159. $main::Repairing and do
  1160. {
  1161. #
  1162. # if codebase is null we need both values
  1163. # test the current arg to see if there's a codebase map for it, if so get the branch
  1164. #
  1165. !$main::CodeBase and do
  1166. {
  1167. SDX::VerifyCBMap($_[$ArgCounter]) and do
  1168. {
  1169. $main::CodeBase = $_[$ArgCounter++];
  1170. $main::Branch = $_[$ArgCounter];
  1171. if ($main::Usage = SDX::VerifyCodeBaseAndBranch($main::CodeBase, $main::Branch))
  1172. {
  1173. $main::CodeBase = "";
  1174. $main::Branch = "";
  1175. }
  1176. $main::V2 and do
  1177. {
  1178. print "\nrepairing, codebase = '$main::CodeBase'\n";
  1179. print "repairing, branch = '$main::Branch'\n";
  1180. };
  1181. };
  1182. };
  1183. #
  1184. # if we didn't use this arg as codebase, pass it on
  1185. #
  1186. (!$main::CodeBase) and SDX::AddUserArg($_[$ArgCounter]);
  1187. };
  1188. }
  1189. $ArgCounter++;
  1190. }
  1191. #
  1192. # maybe return for usage
  1193. #
  1194. $main::Usage and return;
  1195. #
  1196. # at this point all args have been accounted for
  1197. #
  1198. # figure out a couple things we couldn't earlier
  1199. #
  1200. #
  1201. # for a regular enlist-all, set some flags
  1202. #
  1203. ($MinusA and $main::Enlisting) and do
  1204. {
  1205. if (!$main::EnlistAsOther and !$main::EnlistFromProfile)
  1206. {
  1207. $main::EnlistAll = $main::TRUE;
  1208. $main::EnlistGroup = $main::FALSE;
  1209. $main::EnlistSome = $main::FALSE;
  1210. # null out list in case we collected some projects already
  1211. @main::SomeProjects = ();
  1212. }
  1213. else
  1214. {
  1215. $ignore .= " -a";
  1216. }
  1217. };
  1218. #
  1219. # enlist clean if not enlisting as another client
  1220. #
  1221. $MinusC and do
  1222. {
  1223. if (!$main::EnlistAsOther)
  1224. {
  1225. $main::EnlistClean = $main::TRUE;
  1226. }
  1227. else
  1228. {
  1229. $ignore .= " -c";
  1230. }
  1231. };
  1232. #
  1233. # enlisting as another client takes precedence over profiles
  1234. #
  1235. ($MinusP) and do
  1236. {
  1237. if ($main::EnlistAsOther)
  1238. {
  1239. $ignore .= " -p $main::Profile";
  1240. $main::EnlistFromProfile = $main::FALSE;
  1241. $main::Profile = "";
  1242. @main::SomeProjects = ();
  1243. }
  1244. else
  1245. {
  1246. #
  1247. # set flags
  1248. #
  1249. $main::NewEnlist = $main::TRUE;
  1250. $main::IncrEnlist = $main::FALSE;
  1251. $main::CodeBase = $main::ProfileCodeBase;
  1252. $main::Branch = $main::ProfileBranch;
  1253. push @main::SomeProjects, @main::ProfileProjects;
  1254. $main::V2 and do
  1255. {
  1256. $main::Repairing and print "\nrepairing from profile...\n";
  1257. print "\nnew enlist = $main::NewEnlist\n";
  1258. print "incr enlist = $main::IncrEnlist\n";
  1259. print "codebase = '$main::CodeBase'\n";
  1260. print "branch = '$main::Branch'\n";
  1261. print "some projects = '@main::SomeProjects'\n";
  1262. };
  1263. }
  1264. };
  1265. #
  1266. # ignore exclusions if not enlisting as another client
  1267. #
  1268. $MinusX and do
  1269. {
  1270. if (!$main::EnlistAsOther)
  1271. {
  1272. $main::Exclusions = $main::FALSE;
  1273. }
  1274. else
  1275. {
  1276. $ignore .= " -x";
  1277. }
  1278. };
  1279. #
  1280. # if we have args to ignore, say so
  1281. #
  1282. $main::EnlistAsOther and $ignore and printf "\nUsing client %s as a template, ignoring$ignore.\n", "\U$main::OtherClient";
  1283. $main::EnlistFromProfile and $ignore and print "\nUsing profile, ignoring$ignore and/or projects on command line.\n";
  1284. #
  1285. # do some early error checking so we can get usage if needed
  1286. #
  1287. $main::Enlisting and do
  1288. {
  1289. #
  1290. # make sure we're enlisting in either some or all projects
  1291. #
  1292. if (!$main::EnlistAsOther and !$main::EnlistSome and !$main::EnlistAll)
  1293. {
  1294. print "\nMissing projects to enlist, or -a.\n";
  1295. $main::Usage = $main::TRUE;
  1296. }
  1297. #
  1298. # if we're enlisting in only some projects and not as another client,
  1299. # the project list can't be empty
  1300. #
  1301. if ($main::EnlistSome and !$main::EnlistAsOther and ($#main::SomeProjects < 0))
  1302. {
  1303. print "\nMissing projects to enlist. Please specify projects or use -a for all.\n";
  1304. $main::Usage = $main::TRUE;
  1305. }
  1306. };
  1307. #
  1308. # same if defecting...
  1309. #
  1310. $main::Defecting and do
  1311. {
  1312. #
  1313. # make sure we're defecting in either some or all projects
  1314. #
  1315. if (!$main::DefectSome and !$main::DefectAll)
  1316. {
  1317. print "\nMissing projects to defect, or -a.\n";
  1318. $main::Usage = $main::TRUE;
  1319. }
  1320. #
  1321. # if we're defecting in only some projects, the project list
  1322. # can't be empty
  1323. #
  1324. if ($main::DefectSome and ($#main::SomeProjects < 0))
  1325. {
  1326. print "\nMissing projects to defect.\n";
  1327. $main::Usage = $main::TRUE;
  1328. }
  1329. };
  1330. #
  1331. # for now 'sdx branch' or 'sdx integrate' with no args is an error -- we don't want the UI popping up
  1332. # branch and integrate also requires args
  1333. #
  1334. (($main::SDCmd eq "branch" or $main::SDCmd eq "integrate") and $main::UserArgs =~ /^[\s]*$/) and do
  1335. {
  1336. print "\nMissing arguments to 'sdx $main::SDCmd'.\n";
  1337. $main::Usage = $main::TRUE;
  1338. };
  1339. #
  1340. # 'sdx opened -c' without 'default' is an error
  1341. #
  1342. (($main::SDCmd eq "opened") and ($main::UserArgs =~ /-c/ and $main::UserArgs !~ /-c default/)) and do
  1343. {
  1344. print "\n'sdx $main::SDCmd -c' requires 'default' as an argument.\n";
  1345. $main::Usage = $main::TRUE;
  1346. };
  1347. (($main::SDCmd eq "branch" or $main::SDCmd eq "change" or $main::SDCmd eq "user") and $main::UserArgs !~ /-o/) and do
  1348. {
  1349. print "\nOnly the -o switch is supported with 'sdx $main::SDCmd'.\n";
  1350. $main::Usage = $main::TRUE;
  1351. };
  1352. #
  1353. # don't allow "..." ".../*" ".../*.*" or their variations as arg to delete and edit
  1354. #
  1355. ($main::SDCmd eq "deletefile" or $main::SDCmd eq "editfile") and do
  1356. {
  1357. ($main::UserArgs =~ / \.\.\. |\.\.\.[\\\/]\*|\.\.\.[\\\/]+\*\.\* /) and do
  1358. {
  1359. my $ua = $main::UserArgs;
  1360. $ua =~ s/[\t\s]*//g;
  1361. print "\n'$ua' is not supported with 'sdx $main::SDCmd'.\n";
  1362. $main::Usage = $main::TRUE;
  1363. };
  1364. };
  1365. #
  1366. # only allow 'status' arg to sd admin
  1367. #
  1368. ($main::SDCmd eq "admin" and $main::UserArgs =~ / killthread | copyin | copyout | stop/) and do
  1369. {
  1370. print "\nOnly the 'status' command is supported with 'sdx admin'.\n";
  1371. $main::Usage = $main::TRUE;
  1372. };
  1373. #
  1374. # see if we need to check the format of (reverse) integration comments
  1375. #
  1376. # this helps sdx changes -b buildnum find I/RI events in the sd changes output
  1377. # and get build history
  1378. #
  1379. ($main::SDCmd eq "submit" and $main::SubmitComment) and SDX::VerifySubmitComment();
  1380. $main::V4 and do
  1381. {
  1382. print "\nparseargs: cmd line = '@_'\n\n";
  1383. printf "parseargs: op = %s\n", $main::SDCmd;
  1384. printf "parseargs: userargs = '%s'\n", $main::UserArgs;
  1385. printf "parseargs: e = %s\n", $main::Enlisting;
  1386. printf "parseargs: r = %s\n", $main::Repairing;
  1387. printf "parseargs: d = %s\n", $main::Defecting;
  1388. printf "parseargs: o = %s\n", $main::OtherOp;
  1389. printf "parseargs: ea = %s\n", $main::EnlistAll;
  1390. printf "parseargs: es = %s\n", $main::EnlistSome;
  1391. printf "parseargs: da = %s\n", $main::DefectAll;
  1392. printf "parseargs: ds = %s\n", $main::DefectSome;
  1393. print "parseargs: submitcomment = '$main::SubmitComment'\n";
  1394. printf "parseargs: logging = %s\n", $main::Logging;
  1395. printf "parseargs: logfile = '%s'\n", $main::Log;
  1396. printf "parseargs: enlistfromprofile = %s\n", $main::EnlistFromProfile;
  1397. printf "parseargs: profile = '%s'\n", $main::Profile;
  1398. printf "parseargs: newenlist = %s\n", $main::NewEnlist;
  1399. printf "parseargs: increnlist = %s\n", $main::IncrEnlist;
  1400. printf "parseargs: enlistasother = %s\n", $main::EnlistAsOther;
  1401. printf "parseargs: otherclient = '%s'\n", $main::OtherClient;
  1402. printf "parseargs: u = %s\n", $main::Usage;
  1403. printf "parseargs: v1 = %s\n", $main::V1;
  1404. printf "parseargs: v2 = %s\n", $main::V2;
  1405. printf "parseargs: quiet = %s\n", $main::Quiet;
  1406. printf "parseargs: mintools = %s\n", $main::MinimalTools;
  1407. printf "parseargs: sync = %s\n", $main::Sync;
  1408. printf "parseargs: defectwithprejudice = %s\n", $main::DefectWithPrejudice;
  1409. printf "parseargs: sdxroot = %s\n", $main::SDXRoot;
  1410. printf "parseargs: cb = %s\n", $main::CodeBase;
  1411. printf "parseargs: br = %s\n", $main::Branch;
  1412. (($main::MinusI and !$main::Repairing) and !$main::MinusH) and do
  1413. {
  1414. print "parseargs: input form on STDIN:\n";
  1415. foreach (@main::InputForm) { print "'$_'\n"; }
  1416. };
  1417. if ($main::EnlistSome or $main::DefectSome)
  1418. {
  1419. print "\nSome projects on cmd line:\n\n";
  1420. foreach $project (@main::SomeProjects)
  1421. {
  1422. printf "\t%s\n", $project;
  1423. }
  1424. print "\n";
  1425. }
  1426. print "\n";
  1427. };
  1428. }
  1429. # _____________________________________________________________________________
  1430. #
  1431. # AddUserArg
  1432. #
  1433. #
  1434. # Parameters:
  1435. #
  1436. # Output:
  1437. # _____________________________________________________________________________
  1438. sub AddUserArg
  1439. {
  1440. my $arg = $_[0];
  1441. #
  1442. # if the arg is a switch associated with bad cmds
  1443. # see if our cmd is in the list
  1444. #
  1445. ($arg =~ /^[-\/]/ and exists($main::BadCmds{$arg})) and do
  1446. {
  1447. foreach $cmd (@{$main::BadCmds{$arg}})
  1448. {
  1449. ($cmd eq $main::SDCmd) and die("\nThe 'sdx $main::SDCmd $arg' command is not supported.\n");
  1450. }
  1451. };
  1452. $main::V4 and do
  1453. {
  1454. print "adding '$arg ' to '$main::UserArgs'\n";
  1455. };
  1456. $main::UserArgs .= $arg . " ";
  1457. }
  1458. # _____________________________________________________________________________
  1459. #
  1460. # ReadSDMap
  1461. #
  1462. # reads project name and project root (relative path from %SDXROOT%) from
  1463. # %SDXROOT%\sd.map into a list for use by Defect() and OtherOp()
  1464. #
  1465. # Parameters:
  1466. #
  1467. # Output:
  1468. # populates $main::SDMapProjects list
  1469. # _____________________________________________________________________________
  1470. sub ReadSDMap
  1471. {
  1472. my $enlisting = ($_[0] eq "enlist");
  1473. my $defecting = ($_[0] eq "defect");
  1474. my $repairing = ($_[0] eq "repair");
  1475. my $otherop = ($_[0] eq "otherop");
  1476. my $init = ($_[1] eq "init");
  1477. my $line;
  1478. my $repairmsg = $main::FALSE;
  1479. my $enlistmsg = $main::FALSE;
  1480. my $nomapmsg = $main::FALSE;
  1481. my $nokeysmsg = $main::FALSE;
  1482. my $noprojmsg = $main::FALSE;
  1483. #
  1484. # need to re-init this here each time
  1485. #
  1486. @main::SDMapProjects = ();
  1487. $main::V3 and do
  1488. {
  1489. print "op = '$op'\n";
  1490. print "init = '$init'\n";
  1491. };
  1492. if (-e $main::SDMap)
  1493. {
  1494. open(SDMAP, "<$main::SDMap") or die("\nCan't open $main::SDMap for reading.\n");
  1495. while ($line = <SDMAP>)
  1496. {
  1497. #
  1498. # throw away comments, blank lines and certain non-project lines
  1499. #
  1500. $line =~ /^#|^[\t\s]*$/ and next;
  1501. #
  1502. # get the code base
  1503. #
  1504. if ($line =~ /^CODEBASE[\t\s]+/)
  1505. {
  1506. @fields = split(/[\t\s]*=[\t\s]*/, $line);
  1507. $main::SDMapCodeBase = "\U@fields[1]";
  1508. $main::SDMapCodeBase =~ s/[\t\s]*//g;
  1509. next;
  1510. }
  1511. #
  1512. # get the codebase type
  1513. #
  1514. if ($line =~ /^CODEBASETYPE/)
  1515. {
  1516. $main::SDMapCodeBaseType = (split(/[\t\s]*=[\t\s]*/, $line))[1];
  1517. chop $main::SDMapCodeBaseType;
  1518. next;
  1519. }
  1520. #
  1521. # get the branch
  1522. #
  1523. if ($line =~ /^BRANCH/)
  1524. {
  1525. $main::SDMapBranch = (split(/[\t\s]*=[\t\s]*/, $line))[1];
  1526. $main::SDMapBranch =~ s/[\t\s]*//g;
  1527. next;
  1528. }
  1529. #
  1530. # get the client
  1531. #
  1532. if ($line =~ /^CLIENT/)
  1533. {
  1534. $main::SDMapClient = (split(/[\t\s]*=[\t\s]*/, $line))[1];
  1535. $main::SDMapClient =~ s/[\t\s]*//g;
  1536. next;
  1537. }
  1538. #
  1539. # get the list of enlisted depots
  1540. #
  1541. if ($line =~ /^DEPOTS/)
  1542. {
  1543. my $fields = (split(/[\t\s]*=[\t\s]*/, $line))[1];
  1544. @main::SDMapDepots = split(/[\t\s]+/, $fields);
  1545. next;
  1546. }
  1547. #
  1548. # each line is of the form "project = projroot"
  1549. #
  1550. # throw away the '=' and push the project and root into the list
  1551. #
  1552. $line !~ /^(DEPOTS|CLIENT|BRANCH|CODEBASETYPE|CODEBASE)/ and do
  1553. {
  1554. chop $line;
  1555. $line =~ s/[\t\s]+//g;
  1556. @fields = split(/=/, $line);
  1557. push @main::SDMapProjects, [@fields];
  1558. };
  1559. }
  1560. close(SDMAP);
  1561. #
  1562. # if during init and no codebase type or depot list found,
  1563. # fix up the map quietly
  1564. #
  1565. ($init) and do
  1566. {
  1567. (!$main::SDMapCodeBaseType or !@main::SDMapDepots) and do SDX::FixSDMap();
  1568. #
  1569. # track the actively used depots
  1570. #
  1571. # incremental enlist and defect may add/remove depots to/from this list
  1572. #
  1573. @main::ActiveDepots = @main::SDMapDepots;
  1574. };
  1575. $main::V4 and do
  1576. {
  1577. print "\n";
  1578. foreach $p (@main::SDMapProjects)
  1579. {
  1580. printf "readsdm: project, root = %s, %s\n", @$p[0], @$p[1];
  1581. }
  1582. print "\n";
  1583. foreach $p (@main::SDMapDepots)
  1584. {
  1585. printf "readsdm: depot = %s\n", $p;
  1586. }
  1587. print "\nreadsdm: main::SDMapCodeBase = '$main::SDMapCodeBase'\n";
  1588. print "readsdm: main::SDMapBranch = '$main::SDMapBranch'\n";
  1589. print "readsdm: main::SDMapClient = '$main::SDMapClient'\n";
  1590. print "readsdm: main::SDMapCodeBaseType = '$main::SDMapCodeBaseType'\n";
  1591. };
  1592. #
  1593. # return code depends on what we're doing and when
  1594. #
  1595. if ($init)
  1596. {
  1597. #
  1598. # return if we have the keywords else fail with msg
  1599. #
  1600. $enlisting and do
  1601. {
  1602. $main::V4 and print "\nduring init, sd.map exists, enlisting\n";
  1603. $main::SDMapCodeBase and $main::SDMapBranch and $main::SDMapClient and return 1;
  1604. $nokeysmsg = $main::TRUE;
  1605. $repairmsg = $main::TRUE;
  1606. };
  1607. }
  1608. else
  1609. {
  1610. #
  1611. # all we care about in this case is the project list, b/c the map will
  1612. # be rewritten and any missing keywords restored
  1613. #
  1614. # fail silently if at all
  1615. #
  1616. $enlisting and do
  1617. {
  1618. $main::V4 and print "\nduring EDR, sd.map exists, enlisting\n";
  1619. @main::SDMapProjects and return 1;
  1620. };
  1621. }
  1622. #
  1623. # always return successfully when repairing, so we can continue and
  1624. # rewrite any missing lines from the map
  1625. #
  1626. $repairing and do
  1627. {
  1628. $main::V4 and print "\nduring EDR, sd.map exists, repairing\n";
  1629. return 1;
  1630. };
  1631. #
  1632. #
  1633. #
  1634. ($defecting or $otherop) and do
  1635. {
  1636. $main::V4 and print "\nduring EDR, sd.map exists, defecting or otherop\n";
  1637. if ($main::SDMapCodeBase and $main::SDMapBranch and $main::SDMapClient)
  1638. {
  1639. @main::SDMapProjects and return 1;
  1640. $noprojmsg = $main::TRUE;
  1641. }
  1642. else
  1643. {
  1644. $nokeysmsg = $main::TRUE;
  1645. }
  1646. $repairmsg = $main::TRUE;
  1647. };
  1648. #
  1649. # print error msgs
  1650. #
  1651. $nokeysmsg and do
  1652. {
  1653. printf "\n%s is missing one or more required keywords.\n", "\U$main::SDMap";
  1654. };
  1655. $noprojmsg and do
  1656. {
  1657. print "\nNo projects found in \U$main::SDMap.\n";
  1658. };
  1659. $repairmsg and do
  1660. {
  1661. printf "\nRun 'sdx repair %s %s' to update it, then rerun this command.\n", $main::SDMapCodeBase ? "\L$main::SDMapCodeBase" : "<codebase>", $main::SDMapBranch ? $main::SDMapBranch : "<branch>";
  1662. };
  1663. }
  1664. else
  1665. {
  1666. #
  1667. # SD.MAP is missing
  1668. #
  1669. if ($init)
  1670. {
  1671. #
  1672. # assume this is an incremental enlist
  1673. #
  1674. ($enlisting and !$main::NewEnlist) and do
  1675. {
  1676. $nomapmsg = $main::TRUE;
  1677. $enlistmsg = $main::TRUE;
  1678. };
  1679. ($repairing or $defecting or $otherop) and do
  1680. {
  1681. $nomapmsg = $main::TRUE;
  1682. !$repairing and $repairmsg = $main::TRUE;
  1683. };
  1684. }
  1685. else
  1686. {
  1687. $enlisting and do
  1688. {
  1689. $main::V2 and print "\nduring EDR, no sd.map, enlisting\n";
  1690. };
  1691. $repairing and do
  1692. {
  1693. $main::V2 and print "\nduring EDR, no sd.map, repairing\n";
  1694. };
  1695. $defecting and do
  1696. {
  1697. $main::V2 and print "\nduring EDR, no sd.map, defecting\n";
  1698. };
  1699. $otherop and do
  1700. {
  1701. $main::V2 and print "\nduring EDR, no sd.map, otherop\n";
  1702. };
  1703. };
  1704. #
  1705. # print error msgs specific to missing SD.MAP cases
  1706. #
  1707. $nomapmsg and printf "\nCan't find %s to get enlistment information.\n", "\U$main::SDMap";
  1708. $enlistmsg and !$repairmsg and do
  1709. {
  1710. print "\nIf this is a new enlistment please run 'sdx enlist <codebase> <branch>' to\n";
  1711. print "specify the set of sources and the branch you want to enlist in.\n";
  1712. print "\nIf you are adding projects to an existing enlistment, the SD.MAP at\n";
  1713. printf "%s is missing. Run 'sdx repair <codebase> <branch>' to restore\n", "\U$main::SDXRoot";
  1714. print "it, then rerun this command.\n";
  1715. };
  1716. $repairmsg and !$enlistmsg and do
  1717. {
  1718. print "\nVerify that \%SDXROOT\% is set correctly, and that ";
  1719. printf "%s contains\n", "\U$main::SDXRoot";
  1720. printf "a valid enlistment. If it does, run 'sdx repair %s %s'\n", ($main::CodeBase ? $main::CodeBase : "<codebase>"), ($main::Branch ? $main::Branch : "<branch>");
  1721. print "to restore SD.MAP, then rerun this command.\n";
  1722. };
  1723. ($repairmsg or $enlistmsg) and print "\nRun 'sdx repair -?' to see what repairing does to your enlistment.\n";
  1724. }
  1725. return 0;
  1726. }
  1727. # _____________________________________________________________________________
  1728. #
  1729. # FixSDMap
  1730. #
  1731. # silently adds missing keywords to the user's SD.MAP
  1732. #
  1733. # Parameters:
  1734. #
  1735. # Output:
  1736. # _____________________________________________________________________________
  1737. sub FixSDMap
  1738. {
  1739. #
  1740. # if no list of enlisted depots, figure it out and append it to the map
  1741. #
  1742. !@main::SDMapDepots and do
  1743. {
  1744. #
  1745. # figure out the list of active depots
  1746. #
  1747. SDX::OtherOp("enumdepots","");
  1748. #
  1749. # append
  1750. #
  1751. system "attrib -R -H -S $main::SDMap >nul 2>&1";
  1752. open(SDMAP, ">>$main::SDMap") or die("\nCan't append $main::SDMap.\n");
  1753. print SDMAP "\n";
  1754. SDX::WriteSDMapDepots(\@main::SDMapDepots, *SDMAP);
  1755. close SDMAP;
  1756. system "attrib +R +H +S $main::SDMap >nul 2>&1";
  1757. };
  1758. #
  1759. # same for the codebase type
  1760. #
  1761. !$main::SDMapCodeBaseType and do
  1762. {
  1763. #
  1764. # need to act as though we were enlisting to get enough information
  1765. # to determine the type
  1766. #
  1767. $main::CodeBase = $main::SDMapCodeBase;
  1768. if (SDX::VerifyCBMap($main::CodeBase))
  1769. {
  1770. SDX::ReadCodeBaseMap();
  1771. $main::SDMapCodeBaseType = $main::CodeBaseType;
  1772. #
  1773. # throw away results of the map read so we don't get duplicates
  1774. #
  1775. $main::ToolsProject = "";
  1776. $main::ToolsPath = "";
  1777. $main::ToolsProjectPath = "";
  1778. }
  1779. else
  1780. {
  1781. print "\n\nError fixing SD.MAP: can't find codebase map $main::CodeBaseMap.\n";
  1782. die("\nContact the SDX alias.\n");
  1783. }
  1784. #
  1785. # append
  1786. #
  1787. system "attrib -R -H -S $main::SDMap >nul 2>&1";
  1788. open(SDMAP, ">>$main::SDMap") or die("\nCan't append $main::SDMap.\n");
  1789. SDX::WriteSDMapCodeBaseType($main::SDMapCodeBaseType, *SDMAP);
  1790. close SDMAP;
  1791. system "attrib +R +H +S $main::SDMap >nul 2>&1";
  1792. };
  1793. }
  1794. # _____________________________________________________________________________
  1795. #
  1796. # EnumDepots
  1797. #
  1798. # called by FixSDMap by OtherOp to walk the project roots and find SDPORT
  1799. # values
  1800. #
  1801. # Parameters:
  1802. #
  1803. # Output:
  1804. # populates @main::SDMapDepots for writing to SD.MAP
  1805. # _____________________________________________________________________________
  1806. sub EnumDepots
  1807. {
  1808. my $userargs = $_[0];
  1809. my $project = $_[1];
  1810. my $sdini = $_[2];
  1811. my $sp;
  1812. $main::V4 and do
  1813. {
  1814. print "\n\n\nuserargs = '$userargs'\n";
  1815. print "project = '$project'\n";
  1816. };
  1817. #
  1818. # get server:port
  1819. #
  1820. open(INI, "< $sdini") or die("\nCan't read SD.INI.\n");
  1821. while (<INI>)
  1822. {
  1823. /^SDPORT/ and do
  1824. {
  1825. $sp = (split(/=/,$_))[1];
  1826. chop $sp;
  1827. };
  1828. }
  1829. close(INI);
  1830. #
  1831. # add to hash if unique
  1832. #
  1833. unless ($main::DepotsSeen{$sp})
  1834. {
  1835. $main::DepotsSeen{$sp} = 1;
  1836. push @main::SDMapDepots, $sp;
  1837. }
  1838. }
  1839. # _____________________________________________________________________________
  1840. #
  1841. # ListProjects
  1842. #
  1843. # Parameters:
  1844. #
  1845. # Output:
  1846. # _____________________________________________________________________________
  1847. sub ListProjects
  1848. {
  1849. my $userargs = $_[0];
  1850. my $project = $_[1];
  1851. $main::V2 and do
  1852. {
  1853. print "\n\n\nuserargs = '$userargs'\n";
  1854. print "project = '$project'\n";
  1855. };
  1856. SDX::PrintCmd($header, 0);
  1857. for $p (@main::SDMapProjects)
  1858. {
  1859. (@$p[0] eq $project) and print "\n$main::SDXRoot\\@$p[1]\n";
  1860. }
  1861. }
  1862. # _____________________________________________________________________________
  1863. #
  1864. # Enlist
  1865. #
  1866. # Parameters:
  1867. #
  1868. # Output:
  1869. # _____________________________________________________________________________
  1870. sub Enlist
  1871. {
  1872. #
  1873. # munge the codebase map to create project, depot and group lists
  1874. # and figure out what the user wants to enlist in
  1875. #
  1876. if (SDX::InitForEnlist())
  1877. {
  1878. #
  1879. # for each depot we're enlisting in
  1880. # get the list of projects in this depot
  1881. # create/update the client view
  1882. # create/update the SD.MAP
  1883. # write the SD.INIs
  1884. #
  1885. foreach $depot (@main::EnlistDepots)
  1886. {
  1887. $serverport = @$depot[0];
  1888. $main::V3 and print "\n$serverport\n";
  1889. #
  1890. # from the list of all projects to enlist in, create a list of
  1891. # projects found in the current depot only
  1892. #
  1893. @main::ProjectsInThisDepot = ();
  1894. foreach $project (@main::EnlistProjects)
  1895. {
  1896. if ($serverport eq @$project[$main::CBMServerPortField])
  1897. {
  1898. push @main::ProjectsInThisDepot, [@{$project}];
  1899. $main::V3 and print "\t@$project\n";
  1900. }
  1901. }
  1902. print "\n";
  1903. #
  1904. # create or update the client view
  1905. #
  1906. SDX::EnlistProjects($depot, "enlist");
  1907. #
  1908. # upon registering the first client, release the mutex we
  1909. # took ownership of in MakeUniqueClient() so other enlists
  1910. # can continue
  1911. #
  1912. $main::HaveMutex and do
  1913. {
  1914. $main::HaveMutex = $main::FALSE;
  1915. $main::Mutex->release;
  1916. };
  1917. #
  1918. # create/update %SDXROOT%\SD.MAP
  1919. #
  1920. SDX::UpdateSDMap("enlist");
  1921. #
  1922. # create/update %SDXROOT%\SD.MAP
  1923. #
  1924. SDX::UpdateSDINIs("enlist");
  1925. }
  1926. #
  1927. # finish it off
  1928. #
  1929. SDX::FinishEnlist();
  1930. #
  1931. # success
  1932. #
  1933. return 0;
  1934. }
  1935. else
  1936. {
  1937. printf "\nSDX had errors reading the file PROJECTS.%s or in constructing the list of\n", "\U$main::CodeBase";
  1938. print "projects and depots for enlisting.\n";
  1939. #
  1940. # failure
  1941. #
  1942. return 1;
  1943. }
  1944. }
  1945. # _____________________________________________________________________________
  1946. #
  1947. # InitForEnlist
  1948. #
  1949. # Parameters:
  1950. # Command Line Arguments
  1951. #
  1952. # Output:
  1953. # returns 1 if successful, 0 otherwise
  1954. # _____________________________________________________________________________
  1955. sub InitForEnlist
  1956. {
  1957. #
  1958. # do the common init
  1959. #
  1960. SDX::InitForEDR("enlist");
  1961. #
  1962. # set the branch flag
  1963. #
  1964. # one of the following is true about $main::Branch
  1965. # - it matches $main::MasterBranch, in which case we're enlisting in the
  1966. # main sources for all projects for this code base
  1967. # - it matches one of the group build lab branch names, in which case we're
  1968. # enlisting in that lab's branched sources for all projects
  1969. # - it matches some other root-level branch defined by a developer or
  1970. # private lab
  1971. #
  1972. if ($main::Branch eq $main::MasterBranch)
  1973. {
  1974. $main::EnlistingMainBranch = $main::TRUE;
  1975. }
  1976. else
  1977. {
  1978. foreach $br (@main::GroupBranches)
  1979. {
  1980. if ($main::Branch eq $br)
  1981. {
  1982. $main::EnlistingGroupBranch = $main::TRUE;
  1983. last;
  1984. }
  1985. }
  1986. }
  1987. if (!$main::EnlistingMainBranch && !$main::EnlistingGroupBranch)
  1988. {
  1989. $main::EnlistingPrivateBranch = $main::TRUE;
  1990. }
  1991. # more error checking:
  1992. # - branch name can't be a project name
  1993. # - must be enlisting in all or some projects
  1994. # - if only some, project list can't be null
  1995. #
  1996. # verify that the branch the user gave us is not one of the projects
  1997. # in the codebase map. if so, they probably forgot to specify the
  1998. # branch name on the cmd line
  1999. #
  2000. foreach $project (@main::AllProjects)
  2001. {
  2002. ($main::Branch eq @$project[$main::CBMProjectField]) and die("\nBranch name '$main::Branch' appears to be a project.\n");
  2003. }
  2004. #
  2005. # from the lists of all projects, groups and depots, create the lists
  2006. # of just those we'll enlist in
  2007. #
  2008. SDX::MakeTargetLists("enlist");
  2009. #
  2010. # see if we need to use a unique client name
  2011. #
  2012. if ($main::NewEnlist)
  2013. {
  2014. $main::SDClient = SDX::MakeUniqueClient();
  2015. }
  2016. else
  2017. {
  2018. SDX::VerifyAccess();
  2019. }
  2020. #
  2021. # if we have depots and projects to enlist in, continue
  2022. # else politely error-out
  2023. #
  2024. if (@main::EnlistDepots && @main::EnlistProjects)
  2025. {
  2026. if ($main::EnlistAsOther)
  2027. {
  2028. printf "\n\n\nThis script will enlist you in the %s sources using these settings:\n\n", "\U$main::CodeBase";
  2029. }
  2030. else
  2031. {
  2032. printf "\n\n\nThis script will %s in the %s sources", $main::NewEnlist ? "enlist you" : "add projects to your enlistment", "\U$main::CodeBase";
  2033. printf "%susing these settings:\n\n", $main::NewEnlist ? " " : "\n";
  2034. }
  2035. printf "\tRoot directory:\t\t%s\n", "\U$main::SDXRoot";
  2036. printf "\tBranch:\t\t\t%s\n", "\U$main::Branch";
  2037. printf "\tSD client name:\t\t%s\n", $main::SDClient;
  2038. printf "\tSD user name:\t\t%s\n", $main::SDDomainUser;
  2039. $main::EnlistAsOther and printf "\tClient template:\t%s\n", "\U$main::OtherClient";
  2040. #
  2041. # print the projects we're going to enlist in
  2042. #
  2043. $np = $#main::EnlistProjects+1;
  2044. printf "\n\tEnlisting in %s project%s...\n\n", $np, $np > 1 ? "s" : "";
  2045. foreach $project (@main::EnlistProjects)
  2046. {
  2047. printf "\t %s\n", @$project[$main::CBMProjectField];
  2048. }
  2049. #
  2050. # print the depots we're going to enlist in
  2051. #
  2052. $nd = $#main::EnlistDepots+1;
  2053. printf "\n\t...across %s depot%s:\n\n", $nd, $nd > 1 ? "s" : "";
  2054. foreach $depot (@main::EnlistDepots)
  2055. {
  2056. printf "\t %s\n", @$depot[0];
  2057. }
  2058. print "\n\nIF YOU ARE NOT READY TO ENLIST WITH THESE SETTINGS, HIT CTRL-BREAK NOW.\n";
  2059. print " ==================\n\n\n";
  2060. print "Otherwise,\n\n";
  2061. !$main::Quiet and system "pause";
  2062. print "\n\n";
  2063. #
  2064. # warn user if the branch they want doesn't exist
  2065. #
  2066. ###
  2067. ### SDX::VerifyBranch("enlist", $nd) and print "\nWarning: branch '$main::Branch' does not exist in one or more depots\n";
  2068. #
  2069. # if enlisting as another client, make sure the new client we want to create
  2070. # doesn't already exist
  2071. #
  2072. $main::EnlistAsOther and SDX::VerifyClient($nd);
  2073. #
  2074. # add some or all of the depots we're about to enlist in to
  2075. # the active list so they show up in SD.MAP later
  2076. #
  2077. SDX::UpdateActiveDepots("enlist", "");
  2078. $main::V4 and do
  2079. {
  2080. printf "\n";
  2081. printf "initforenlist: cb=%s\n", $main::CodeBase;
  2082. printf "initforenlist: cbm=%s\n", $main::CodeBaseMap;
  2083. printf "initforenlist: mb=%s\n", $main::MasterBranch;
  2084. printf "initforenlist: cv=%s\n", $main::ClientView;
  2085. printf "\n";
  2086. };
  2087. return 1;
  2088. }
  2089. else
  2090. {
  2091. !@main::EnlistProjects and print "\nNo projects found. Unable to enlist.\n" and return 0;
  2092. !@main::EnlistDepots and print "\nNo depots found. Unable to enlist.\n" and return 0;
  2093. }
  2094. }
  2095. # _____________________________________________________________________________
  2096. #
  2097. # UpdateActiveDepots
  2098. #
  2099. # Add or remove server:port values to active depot list, depending on
  2100. # operation
  2101. #
  2102. # Parameters:
  2103. #
  2104. # Output:
  2105. # _____________________________________________________________________________
  2106. sub UpdateActiveDepots
  2107. {
  2108. my $op = $_[0];
  2109. my $sp = $_[1];
  2110. my $enlisting = ($op eq "enlist");
  2111. my $defecting = ($op eq "defect");
  2112. ($enlisting) and do
  2113. {
  2114. #
  2115. # on a clean enlist the list of active depots is
  2116. # those the user will enlist in
  2117. #
  2118. # active depot list is written to SD.MAP after enlisting
  2119. #
  2120. ($main::NewEnlist) and do
  2121. {
  2122. my @unsorted = ();
  2123. for $depot (@main::EnlistDepots)
  2124. {
  2125. push @unsorted, @$depot[0];
  2126. }
  2127. #
  2128. # want this sorted
  2129. #
  2130. @main::ActiveDepots = SDX::SortDepots(\@unsorted);
  2131. };
  2132. #
  2133. # on an incremental enlist, add new depots only
  2134. #
  2135. ($main::IncrEnlist) and do
  2136. {
  2137. my %hash = ();
  2138. for $depot (@main::ActiveDepots)
  2139. {
  2140. $hash{$depot} = 1;
  2141. }
  2142. $main::V3 and do
  2143. {
  2144. print "\nhash:\n";
  2145. while (($k,$v) = each %hash)
  2146. {
  2147. printf " %-50s\t%s\n", $k, $v;
  2148. }
  2149. };
  2150. for $depot (@main::EnlistDepots)
  2151. {
  2152. my $sp = @$depot[0];
  2153. ($hash{$sp} != 1) and do
  2154. {
  2155. push @main::ActiveDepots, $sp;
  2156. };
  2157. }
  2158. @main::ActiveDepots = SDX::SortDepots(\@main::ActiveDepots);
  2159. };
  2160. };
  2161. #
  2162. # null out dead server:port in active list
  2163. #
  2164. ($defecting) and do
  2165. {
  2166. $main::V3 and do
  2167. {
  2168. print "\nbefore:\n";
  2169. for $d (@main::ActiveDepots)
  2170. {
  2171. print " '$d'\n";
  2172. }
  2173. };
  2174. grep {s/$sp//g} @main::ActiveDepots;
  2175. $main::V3 and do
  2176. {
  2177. print "\nafter:\n";
  2178. for $d (@main::ActiveDepots)
  2179. {
  2180. print " '$d'\n";
  2181. }
  2182. };
  2183. };
  2184. }
  2185. # _____________________________________________________________________________
  2186. #
  2187. # EnlistProjects
  2188. #
  2189. # Parameters:
  2190. #
  2191. # Output:
  2192. # _____________________________________________________________________________
  2193. sub EnlistProjects
  2194. {
  2195. $depot = $_[0];
  2196. $op = $_[1];
  2197. $serverport = @$depot[0];
  2198. if ($main::EnlistAsOther)
  2199. {
  2200. #
  2201. # register a new view using another client as a template
  2202. #
  2203. my $desc = 0;
  2204. my $pr = 0;
  2205. unlink $main::ClientView;
  2206. #
  2207. # Root: field for client view depends on depot type
  2208. #
  2209. # for type 1 (1 project/depot), root includes project name
  2210. # for type 2 (N projects/depot), root is just main::SDXRoot
  2211. #
  2212. # root is at least SDXRoot in either case
  2213. #
  2214. $root = $main::SDXRoot;
  2215. (@{$main::DepotType{$serverport}}[0] == 1) and $root = SDX::Type1Root($root);
  2216. #
  2217. # dump the other client into a list
  2218. #
  2219. @lines = `sd.exe -p $serverport client -o $main::OtherClient`;
  2220. $main::V3 and print "otherclient = '@lines'\n\n";
  2221. #
  2222. # munge the other's view to create a template
  2223. #
  2224. open(CLIENTVIEW, ">$main::ClientView") or die("\nCan't open $main::ClientView for writing.\n");
  2225. #
  2226. # if OtherClient is a unique name, double up on the '\' so
  2227. # the s///gi works correctly
  2228. #
  2229. my $other = $main::OtherClient;
  2230. $other =~ s/\\/\\\\/g;
  2231. #
  2232. # transmogrify the client spec lines
  2233. #
  2234. foreach $line (@lines)
  2235. {
  2236. #
  2237. # if the most recent line was the description, the current line is its text
  2238. #
  2239. $desc and do
  2240. {
  2241. $line =~ s/^[\t\s]+.+/\tCreated by $main::SDDomainUser./g;
  2242. print CLIENTVIEW "$line";
  2243. $desc = 0;
  2244. next;
  2245. };
  2246. # throw away comments and certain other lines
  2247. $line =~ /(Update|Access):|^#/ and next;
  2248. # replace Client: with our client
  2249. $line =~ s/^Client:[\t\s]*.+/Client: $main::SDClient/g;
  2250. # replace owner name with our user name
  2251. $line =~ s/^Owner:[\t\s]*.+/Owner: $main::SDDomainUser/g;
  2252. # found the desc line, set a flag and replace it next time through
  2253. $line =~ /^Description:/ and $desc = 1;
  2254. # replace the old root with ours
  2255. $line =~ s/^Root:[\t\s]*.+/Root: $root/g;
  2256. # replace other client name in view lines with ours
  2257. $line =~ s/$other/$main::SDClient/gi;
  2258. print CLIENTVIEW "$line";
  2259. }
  2260. close(CLIENTVIEW);
  2261. $main::V2 and do
  2262. {
  2263. print "==========\n";
  2264. system "type $main::ClientView";
  2265. print "==========\n";
  2266. };
  2267. }
  2268. else
  2269. {
  2270. #
  2271. # create/update the view spec
  2272. #
  2273. SDX::CreateView($depot, $op);
  2274. }
  2275. #
  2276. # register the new/updated view
  2277. #
  2278. system "sd.exe -p $serverport client -i < $main::ClientView";
  2279. }
  2280. # _____________________________________________________________________________
  2281. #
  2282. # FinishEnlist
  2283. #
  2284. # Finish up by:
  2285. # maybe syncing projects for the user
  2286. # generating SDINIT and alias files
  2287. # syncing the tools dir
  2288. # syncing any other dirs specified by the codebase map
  2289. # providing friendly verbage
  2290. #
  2291. # Parameters:
  2292. # none
  2293. #
  2294. # Output:
  2295. # _____________________________________________________________________________
  2296. sub FinishEnlist
  2297. {
  2298. #
  2299. # cleanup
  2300. #
  2301. unlink $main::ClientView;
  2302. #
  2303. # maybe unghost
  2304. #
  2305. $main::Sync and SDX::SyncFiles("enlist", $main::Null, $main::Null);
  2306. #
  2307. # give the user some direction on how to get started
  2308. #
  2309. # if the codebase map identified a tools dir, point them to that
  2310. # otherwise copy down the tools for them
  2311. #
  2312. #
  2313. # give the user the SD/SDX tools, batch files for aliases and SDX commands
  2314. #
  2315. SDX::ToolsEtc("enlist");
  2316. #
  2317. # also sync any OtherDirs at this time
  2318. #
  2319. @main::OtherDirs and SDX::SyncOtherDirs("enlist");
  2320. #
  2321. # if NT, addfile a default \developer\<username>\setenv.cmd
  2322. # not there yet
  2323. #
  2324. ("\U$main::CodeBase" eq "NT") and SDX::WriteDefaultSetEnv();
  2325. #
  2326. # verbage for a succesful enlist
  2327. #
  2328. print "\nDone.\n";
  2329. $main::NewEnlist and do
  2330. {
  2331. $main::SDXRoot =~ tr/a-z/A-Z/;
  2332. $main::CodeBase =~ tr/a-z/A-Z/;
  2333. $sdtools = $main::SDXRoot . "\\sdtools";
  2334. print "\n\nThe directory $main::SDXRoot is now enlisted in the $main::CodeBase sources.\n";
  2335. print "\nThese SDX files were placed in your enlistment:\n";
  2336. if ($main::ToolsProject)
  2337. {
  2338. print "\n $main::SDXRoot\n";
  2339. printf "\t%-24smap to project roots and SD.INIs\n", "SD.MAP";
  2340. print "\n \U$main::ToolsProjectPath\n";
  2341. printf "\t%-24saliases for logging SDX output\n", "ALIAS.SDX";
  2342. printf "\t%-24saliases for navigating your enlistment\n", "ALIAS." . $main::CodeBase;
  2343. $main::CodeBaseMapFile =~ tr/a-z/A-Z/;
  2344. printf "\t%-24scodebase map for future enlist/defect/repair\n", $main::CodeBaseMapFile;
  2345. printf "\t%-24ssets default Source Depot vars and aliases\n", "SDINIT.CMD";
  2346. printf "\t%-24sscripts for cross-depot commands\n", "SDX.\*";
  2347. if (
  2348. "\U$main::CodeBase" eq "NT" or
  2349. "\U$main::CodeBase" eq "NTSDK" or
  2350. ("\U$main::CodeBase" eq "NTTEST" and !$main::RestrictRoot) or
  2351. "\U$main::CodeBase" eq "NT.INTL" or
  2352. "\U$main::CodeBase" eq "MPC" or
  2353. "\U$main::CodeBase" eq "NGWS" or
  2354. "\U$main::CodeBase" eq "MGMT" or
  2355. "\U$main::CodeBase" eq "MOM" or
  2356. "\U$main::CodeBase" eq "PDDEPOT" or
  2357. "\U$main::CodeBase" eq "WINMEDIA"
  2358. )
  2359. {
  2360. printf "\n\nRun\n\n %s\\RAZZLE.CMD%s\n\nto start building.\n\n","\U$main::ToolsProjectPath", ($main::MinimalTools) ? " no_certcheck" : "";
  2361. }
  2362. else
  2363. {
  2364. print "\n\nTo use Source Depot, your build environment must:\n";
  2365. print "\n set SDXROOT=$main::SDXRoot\n";
  2366. printf " set PATH=\%SDXROOT\%\\%s;\%SDXROOT\%\\%s\\\%PROCESSOR_ARCHITECTURE\%;\%PATH\%\n", $main::ToolsPath ? "\U$main::ToolsPath" : "\U$main::ToolsProject", $main::ToolsPath ? "\U$main::ToolsPath" : "\U$main::ToolsProject";
  2367. printf " call %s\\SDINIT.CMD\n", "\U$main::ToolsProjectPath";
  2368. }
  2369. }
  2370. else
  2371. {
  2372. print "\n $main::SDXRoot\n";
  2373. printf "\t%-24saliases for logging SDX output\n", "ALIAS.SDX";
  2374. printf "\t%-24saliases for navigating your enlistment\n", "ALIAS." . $main::CodeBase;
  2375. printf "\t%-24smap to project roots and SD.INIs\n", "SD.MAP";
  2376. printf "\t%-24ssets default Source Depot vars and aliases\n", "SDINIT.CMD";
  2377. print "\n $sdtools\n";
  2378. printf "\t%-24sPerl runtimes\n", "PERL\*";
  2379. $main::CodeBaseMapFile =~ tr/a-z/A-Z/;
  2380. printf "\t%-24scodebase map for future enlist/defect/repair\n", $main::CodeBaseMapFile;
  2381. printf "\t%-24sSource Depot client\n", "SD.EXE";
  2382. printf "\t%-24sscripts for cross-depot commands\n", "SDX.\*";
  2383. print "\n\nTO USE SDX/SD\n-------------\n";
  2384. print "Run $main::SDINIT. This will\n\n";
  2385. print " - set default Source Depot environment variables\n\n";
  2386. !$main::ToolsProject and print " - include $main::SDXRoot\\sdtools in your PATH\n\n";
  2387. print " - turn on aliases to log SDX output to $main::SDXRoot\\<command>.LOG\n";
  2388. print " and for changing between source projects\n\n";
  2389. print " - look for the file SDVARS.CMD and run it if found. This is\n";
  2390. print " useful for customizing Source Depot settings like SDEDITOR or\n";
  2391. print " SDPASSWD, adding other aliases, etc.\n";
  2392. print "\nYou can then run SDX or SD commands.\n";
  2393. !$main::Sync and do
  2394. {
  2395. print "\n\nYou may want to run 'sdx sync' to sync files in your enlistment.\n";
  2396. };
  2397. }
  2398. };
  2399. }
  2400. # _____________________________________________________________________________
  2401. #
  2402. # Repair
  2403. #
  2404. # Parameters:
  2405. #
  2406. # Output:
  2407. # _____________________________________________________________________________
  2408. sub Repair
  2409. {
  2410. #
  2411. # munge the codebase map to create project, depot and group lists,
  2412. # then query the depots to figure out which depots and projects the
  2413. # user is already enlisted in
  2414. #
  2415. if (SDX::InitForRepair())
  2416. {
  2417. #
  2418. # if rewriting SD.INIs, SD.MAP must also be rewritten
  2419. # easiest to just initially remove it
  2420. #
  2421. ($main::MinusI) and unlink $main::SDMap;
  2422. #
  2423. # for each depot we're repairing
  2424. # get the list of projects in this depot
  2425. # create/update the client view
  2426. # create/update the SD.MAP
  2427. # write the SD.INIs
  2428. #
  2429. foreach $depot (@main::RepairDepots)
  2430. {
  2431. $serverport = @$depot[0];
  2432. $main::V2 and print "\n$serverport\n";
  2433. #
  2434. # from the list of all projects to repair, create a list of
  2435. # projects found in the current depot only
  2436. #
  2437. @main::ProjectsInThisDepot = ();
  2438. foreach $project (@main::RepairProjects)
  2439. {
  2440. if ($serverport eq @$project[$main::CBMServerPortField])
  2441. {
  2442. push @main::ProjectsInThisDepot, [@{$project}];
  2443. $main::V2 and print "\t@$project\n";
  2444. }
  2445. }
  2446. print "\n";
  2447. #
  2448. # create or update the client view
  2449. # if not repairing only SD.INIs
  2450. #
  2451. if ($main::MinusI)
  2452. {
  2453. print "Repairing enlistment for depot $serverport.\n";
  2454. }
  2455. else
  2456. {
  2457. SDX::EnlistProjects($depot, "repair");
  2458. }
  2459. #
  2460. # create/update %SDXROOT%\SD.MAP
  2461. #
  2462. SDX::UpdateSDMap("repair");
  2463. #
  2464. # create/update <projroot>\SD.INI
  2465. #
  2466. SDX::UpdateSDINIs("repair");
  2467. }
  2468. #
  2469. # finish it off
  2470. #
  2471. SDX::FinishRepair();
  2472. #
  2473. # success
  2474. #
  2475. return 0;
  2476. }
  2477. else
  2478. {
  2479. printf "\nThis client wasn't found in the depot(s) for the %s sources. Use 'sd -p\n", "\U$main::CodeBase";
  2480. print "<server:port> clients' to verify that $main::SDClient actually has an enlistment.\n\n";
  2481. #
  2482. # failure
  2483. #
  2484. return 1;
  2485. }
  2486. }
  2487. # _____________________________________________________________________________
  2488. #
  2489. # InitForRepair
  2490. #
  2491. # Parameters:
  2492. # Command Line Arguments
  2493. #
  2494. # Output:
  2495. #
  2496. # _____________________________________________________________________________
  2497. sub InitForRepair
  2498. {
  2499. #
  2500. # do the common init
  2501. #
  2502. SDX::InitForEDR("repair");
  2503. #
  2504. # query the depots and make the lists of depots and projects the user
  2505. # is enlisted in
  2506. #
  2507. if (SDX::GetProjectsToRepair())
  2508. {
  2509. SDX::VerifyAccess();
  2510. #
  2511. # starting verbage
  2512. #
  2513. printf "\n\n\nThis script will repair your enlistment in the %s sources using these\n", "\U$main::CodeBase";
  2514. printf "settings:\n\n";
  2515. printf "\tRoot directory:\t\t%s\n", "\U$main::SDXRoot";
  2516. printf "\tCode branch:\t\t%s\n", "\U$main::Branch";
  2517. printf "\tSD client name:\t\t%s\n", $main::SDClient;
  2518. printf "\tSD user name:\t\t%s\n", $main::SDDomainUser;
  2519. #
  2520. # print the projects to repair
  2521. #
  2522. $np = $#main::RepairProjects+1;
  2523. printf "\n\tRepairing %s%s project%s...\n\n", ($main::MinusI) ? "SD.INIs for " : "", $np, $np > 1 ? "s" : "";
  2524. foreach $project (@main::RepairProjects)
  2525. {
  2526. printf "\t %s\n", @$project[$main::CBMProjectField];
  2527. }
  2528. #
  2529. # print the depots to repair
  2530. #
  2531. $nd = $#main::RepairDepots+1;
  2532. printf "\n\t...across %s depot%s:\n\n", $nd, $nd > 1 ? "s" : "";
  2533. foreach $depot (@main::RepairDepots)
  2534. {
  2535. printf "\t %s\n", @$depot[0];
  2536. }
  2537. print "\n\nIF THESE SETTINGS ARE NOT CORRECT, HIT CTRL-BREAK NOW.\n";
  2538. print " ==================\n\n\n";
  2539. print "Otherwise,\n\n";
  2540. !$main::Quiet and system "pause";
  2541. print "\n\n";
  2542. return 1;
  2543. }
  2544. else
  2545. {
  2546. printf "\nNo depots or projects found for client %s. Unable to repair.\n", "\U$main::SDClient";
  2547. return 0;
  2548. }
  2549. }
  2550. # _____________________________________________________________________________
  2551. #
  2552. # FinishRepair
  2553. #
  2554. # Finish up by:
  2555. # maybe syncing projects for the user
  2556. # generating SDINIT and alias files
  2557. # syncing the tools dir
  2558. # syncing any other dirs specified by the codebase map
  2559. # providing friendly verbage
  2560. #
  2561. # Parameters:
  2562. # none
  2563. #
  2564. # Output:
  2565. # _____________________________________________________________________________
  2566. sub FinishRepair
  2567. {
  2568. #
  2569. # cleanup
  2570. #
  2571. unlink $main::ClientView;
  2572. #
  2573. # sync files or tools if doing more than rewriting SD.INIs
  2574. #
  2575. !$main::MinusI and do
  2576. {
  2577. #
  2578. # maybe re-sync
  2579. #
  2580. $main::Sync and SDX::SyncFiles("repair", $main::Null, $main::Null);
  2581. #
  2582. # give the user the SD/SDX tools, batch files for aliases and SDX commands
  2583. #
  2584. SDX::ToolsEtc("repair");
  2585. #
  2586. # also sync any OtherDirs at this time
  2587. #
  2588. @main::OtherDirs and SDX::SyncOtherDirs("repair");
  2589. };
  2590. #
  2591. # verbage for a succesful repair
  2592. #
  2593. if ($main::MinusI)
  2594. {
  2595. printf "\n\nThe SD.INIs in your %s enlistment have been repaired.\n", "\U$main::CodeBase";
  2596. }
  2597. else
  2598. {
  2599. printf "\n\nYour %s enlistment has been repaired.\n", "\U$main::CodeBase";
  2600. }
  2601. (!$main::Sync and !$main::MinusI) and do
  2602. {
  2603. print "\nIf you are missing source files, run 'sd sync -f [filespec]' or 'sdx sync -f'\n";
  2604. print "to restore them.\n";
  2605. };
  2606. }
  2607. # _____________________________________________________________________________
  2608. #
  2609. # Defect
  2610. #
  2611. # Parameters:
  2612. #
  2613. # Output:
  2614. # returns 0 if successful, 1 otherwise
  2615. # _____________________________________________________________________________
  2616. sub Defect
  2617. {
  2618. #
  2619. # munge the codebase map to create project, depot and group lists
  2620. # and figure out what the user wants to defect from
  2621. #
  2622. if (SDX::InitForDefect())
  2623. {
  2624. #
  2625. # for each depot we're defecting from
  2626. # get the list of projects in this depot
  2627. # create/update the client view
  2628. # create/update the SD.MAP
  2629. # write the SD.INIs
  2630. #
  2631. foreach $depot (@main::DefectDepots)
  2632. {
  2633. $serverport = @$depot[0];
  2634. $main::V2 and print "\n$serverport\n";
  2635. #
  2636. # from the list of all projects to defect from, create a list of
  2637. # projects found in the current depot only
  2638. #
  2639. @main::ProjectsInThisDepot = ();
  2640. foreach $project (@main::DefectProjects)
  2641. {
  2642. if ($serverport eq @$project[$main::CBMServerPortField])
  2643. {
  2644. push @main::ProjectsInThisDepot, [@{$project}];
  2645. $main::V2 and print "\t@$project\n";
  2646. }
  2647. }
  2648. print "\n";
  2649. #
  2650. # "update" the projects and INIs by removing them
  2651. #
  2652. SDX::UpdateSDINIs("defect");
  2653. #
  2654. # remove entries from SD.MAP or remove it entirely if defecting all
  2655. #
  2656. SDX::UpdateSDMap("defect");
  2657. #
  2658. # remove entries from client view, or delete client if
  2659. # entire view would be removed
  2660. #
  2661. SDX::DefectProjects($depot);
  2662. print "ok.\n";
  2663. }
  2664. #
  2665. # finish it off
  2666. #
  2667. SDX::FinishDefect();
  2668. #
  2669. # success
  2670. #
  2671. return 0;
  2672. }
  2673. else
  2674. {
  2675. printf "\nSDX had errors reading the file PROJECTS.%s or constructing the list of\n", "\U$main::CodeBase";
  2676. print "projects and depots for defecting. Please contact the SDX alias.\n";
  2677. #
  2678. # failure
  2679. #
  2680. return 1;
  2681. }
  2682. }
  2683. # _____________________________________________________________________________
  2684. #
  2685. # InitForDefect
  2686. #
  2687. # Parameters:
  2688. # Command Line Arguments
  2689. #
  2690. # Output:
  2691. # populates @main::DefectDepots and @main::DefectProjects
  2692. # returns 1 if successful or 0 if no projects left in list
  2693. # _____________________________________________________________________________
  2694. sub InitForDefect
  2695. {
  2696. #
  2697. # do the common init
  2698. #
  2699. SDX::InitForEDR("defect");
  2700. #
  2701. # verify that the branch the user gave us is not one of the
  2702. # projects in the codebase map. if so, they probably forgot to specify
  2703. # the branch name on the cmd line
  2704. #
  2705. foreach $project (@main::AllProjects)
  2706. {
  2707. ($main::Branch eq @$project[$main::CBMProjectField]) and die("\nBranch name '$main::Branch' appears to be a project.\n");
  2708. }
  2709. #
  2710. # from the lists of all projects, groups and depots, create the lists
  2711. # of just those we'll defect from
  2712. #
  2713. SDX::MakeTargetLists("defect");
  2714. #
  2715. # verify access to the servers now that we have the list of depots made by MakeTargetLists
  2716. #
  2717. SDX::VerifyAccess();
  2718. #
  2719. # if we have depots and projects to defect from, continue
  2720. # else politely error-out
  2721. #
  2722. if (@main::DefectDepots && @main::DefectProjects)
  2723. {
  2724. #
  2725. # starting verbage
  2726. #
  2727. printf "\n\n\nThis script will defect you from projects in the %s sources using these\n", "\U$main::CodeBase";
  2728. printf "settings:\n\n";
  2729. printf "\tRoot directory:\t\t%s\n", "\U$main::SDXRoot";
  2730. printf "\tCode branch:\t\t%s\n", "\U$main::Branch";
  2731. printf "\tSD client name:\t\t%s\n", $main::SDClient;
  2732. printf "\tSD user name:\t\t%s\n", $main::SDDomainUser;
  2733. #
  2734. # print the projects to defect
  2735. #
  2736. $np = $#main::DefectProjects+1;
  2737. printf "\n\tDefecting from %s project%s...\n\n", $np, $np > 1 ? "s" : "";
  2738. foreach $project (@main::DefectProjects)
  2739. {
  2740. printf "\t %s\n", @$project[$main::CBMProjectField];
  2741. }
  2742. #
  2743. # print the depots to defect
  2744. #
  2745. $nd = $#main::DefectDepots+1;
  2746. printf "\n\t...across %s depot%s:\n\n", $nd, $nd > 1 ? "s" : "";
  2747. foreach $depot (@main::DefectDepots)
  2748. {
  2749. printf "\t %s\n", @$depot[0];
  2750. }
  2751. $main::DefectWithPrejudice and printf "\n\tALL FILES AND DIRECTORIES in %s will be deleted.\n", $np > 1 ? "these projects" : "this project";
  2752. print "\n\nIF THESE SETTINGS ARE NOT CORRECT, HIT CTRL-BREAK NOW.\n";
  2753. print " ==================\n\n\n";
  2754. print "Otherwise,\n\n";
  2755. !$main::Quiet and system "pause";
  2756. print "\n\n";
  2757. #
  2758. # verify that the branch the user wants exists in each depot
  2759. #
  2760. ###
  2761. ### SDX::VerifyBranch("defect", $nd);
  2762. #
  2763. # abort if the client still has files open
  2764. #
  2765. my @open = ();
  2766. if (@open = SDX::FilesOpen())
  2767. {
  2768. print "\n\nUnable to defect. Your client has these files open:\n\n";
  2769. print @open;
  2770. print "\nSubmit or revert the files, then rerun this command.\n";
  2771. die("\n");
  2772. }
  2773. return 1;
  2774. }
  2775. else
  2776. {
  2777. print "\nNo depots or projects found. Unable to defect.\n";
  2778. return 0;
  2779. }
  2780. }
  2781. # _____________________________________________________________________________
  2782. #
  2783. # DefectProjects
  2784. #
  2785. # Parameters:
  2786. #
  2787. # Output:
  2788. # _____________________________________________________________________________
  2789. sub DefectProjects
  2790. {
  2791. my $depot = $_[0];
  2792. my $serverport = @$depot[0];
  2793. if ($main::DefectAll)
  2794. {
  2795. #
  2796. # delete client completely
  2797. #
  2798. SDX::DeleteClient($serverport);
  2799. }
  2800. else
  2801. {
  2802. #
  2803. # for this depot, remove some projects from the view
  2804. #
  2805. # if we have a reduced view to register, do it
  2806. # otherwise delete the client entirely from this depot
  2807. #
  2808. if (SDX::RemoveFromView($depot))
  2809. {
  2810. print "\n";
  2811. system "sd.exe -p $serverport client -i < $main::ClientView";
  2812. }
  2813. else
  2814. {
  2815. print "\n";
  2816. #
  2817. # delete client completely
  2818. #
  2819. SDX::DeleteClient($serverport);
  2820. }
  2821. }
  2822. }
  2823. # _____________________________________________________________________________
  2824. #
  2825. # DeleteClient
  2826. #
  2827. # Delete $main::SDClient. Since clients are locked by default, non-
  2828. # superusers can't delete their client, even with -f, so unlock the client
  2829. # before deleting
  2830. #
  2831. # Parameters:
  2832. # none
  2833. #
  2834. # Output:
  2835. # _____________________________________________________________________________
  2836. sub DeleteClient
  2837. {
  2838. my $serverport = $_[0];
  2839. my @pending = ();
  2840. my @changenums = ();
  2841. #
  2842. # delete any pending changes owned by this client so we don't orphan them
  2843. #
  2844. @pending = grep(/$main::SDClient \*pending/, `sd.exe -p $serverport -c $main::SDClient changes -s pending`);
  2845. @pending and do
  2846. {
  2847. my $line;
  2848. $main::V2 and print "pending = '@pending'\n";
  2849. my @fields = ();
  2850. foreach $line (@pending)
  2851. {
  2852. @fields = split(/ /,$line);
  2853. push @changenums, $fields[1];
  2854. }
  2855. $main::V2 and print "changenums = '@changenums'\n";
  2856. foreach $line (@changenums)
  2857. {
  2858. `sd.exe -p $serverport change -f -d $line`;
  2859. }
  2860. };
  2861. #
  2862. # delete it
  2863. #
  2864. system "sd.exe -p $serverport client -d $main::SDClient";
  2865. #
  2866. # remove depot from the list of active depots
  2867. #
  2868. SDX::UpdateActiveDepots("defect", $serverport);
  2869. }
  2870. # _____________________________________________________________________________
  2871. #
  2872. # FinishDefect
  2873. #
  2874. # Finish up by:
  2875. #
  2876. # Parameters:
  2877. # none
  2878. #
  2879. # Output:
  2880. # _____________________________________________________________________________
  2881. sub FinishDefect
  2882. {
  2883. #
  2884. # cleanup
  2885. #
  2886. unlink $main::ClientView;
  2887. #
  2888. # write SD.MAP one last time to update the depot list
  2889. #
  2890. if (SDX::GetMapProjects("defect"))
  2891. {
  2892. SDX::WriteSDMap(\@main::ExistingMap);
  2893. }
  2894. #
  2895. # remove root files only if defecting the world
  2896. #
  2897. $main::DefectAll and SDX::ToolsEtc("defect");
  2898. #
  2899. # verbage for a successful defect
  2900. #
  2901. print "\n\nOne or more projects were successfully defected.\n";
  2902. $main::DefectAll and do
  2903. {
  2904. my $path = $main::ToolsProject ? $main::ToolsProjectPath : ($main::SDXRoot . "\\sdtools");
  2905. printf "\nThe SD/SDX tools were in use. Please remove %s manually.\n", "\U$path";
  2906. };
  2907. }
  2908. # _____________________________________________________________________________
  2909. #
  2910. # OtherOp
  2911. # called from sdx.pl to call an SD cmd
  2912. #
  2913. # Parameters:
  2914. # $sdcmd -- basic SD cmd as defined in %main::SDCmds
  2915. # $fulluserargs -- all args as passed in
  2916. #
  2917. # Output:
  2918. # _____________________________________________________________________________
  2919. sub OtherOp
  2920. {
  2921. my $sdcmd = $_[0];
  2922. my $fulluserargs = $_[1];
  2923. my $cmdtype = 0;
  2924. my $defcmd = "";
  2925. my $cmd = "";
  2926. my $fullcmd = "";
  2927. my $project = "";
  2928. my $userargs = "";
  2929. my $string = "";
  2930. !$sdcmd and die("\nMissing command to OtherOp().\n");;
  2931. #
  2932. # get the cmd string and default args, and maybe
  2933. # append user args
  2934. #
  2935. $defcmd = $main::SDCmds{$sdcmd}{defcmd};
  2936. $cmdtype = $main::SDCmds{$sdcmd}{type};
  2937. #
  2938. # strip the '~proj' args out of userargs so they don't pass to SD
  2939. #
  2940. $userargs = $fulluserargs;
  2941. $userargs =~ s/~\w+//g;
  2942. #
  2943. # see if we're creating a lab or private branch
  2944. #
  2945. # then map lbranch/pbranch to "branch" cmd so -o and -d will work
  2946. #
  2947. my $privatebranch = ($defcmd eq "pbranch" and $userargs !~ /-[do]+/);
  2948. my $labbranch = ($defcmd eq "lbranch" and $userargs !~ /-[do]+/);
  2949. ($defcmd eq "pbranch" or $defcmd eq "lbranch") and $defcmd = "branch";
  2950. #
  2951. # get the complete command into one string
  2952. #
  2953. $cmd = $defcmd . " " . $main::SDCmds{$sdcmd}{defarg} . $userargs;
  2954. $main::V2 and do
  2955. {
  2956. print "defcmd = '$defcmd'\n";
  2957. print "fulluserargs = '$fulluserargs'\n";
  2958. print "userargs = '$userargs'\n";
  2959. print "type = '$cmdtype'\n";
  2960. print "defargs = '$main::SDCmds{$sdcmd}{defarg}'\n";
  2961. print "cmd = '$cmd'\n";
  2962. };
  2963. print "\n";
  2964. #
  2965. # maybe delete previous log
  2966. #
  2967. $main::Logging and unlink $main::Log;
  2968. #
  2969. # if branching, give the user some instructions
  2970. #
  2971. $privatebranch and SDX::PrivateBranch($userargs, $main::Null, $main::Null, "start");
  2972. $labbranch and SDX::LabBranch($userargs, $main::Null, $main::Null, "start");
  2973. #
  2974. # for type 1 commands, where the scope as it appears to the user is per-
  2975. # project, loop through the project list and run $defcmd
  2976. #
  2977. # note that for type 1 codebases (with one project per depot), all commands
  2978. # are essentially type 1
  2979. #
  2980. $cmdtype == 1 and do
  2981. {
  2982. #
  2983. # for each project, change to it's root and run $defcmd
  2984. #
  2985. foreach $projectandroot (@main::SDMapProjects)
  2986. {
  2987. $project = @$projectandroot[0];
  2988. #
  2989. # common header
  2990. #
  2991. $header = "\n---------------- \U$project\n";
  2992. #
  2993. # skip this project if the user negated it on the cmd line with '~project'
  2994. #
  2995. $fulluserargs =~ /~$project / and next;
  2996. #
  2997. # get path to SD.INI, make sure we have it, and cd there
  2998. #
  2999. $fullprojectroot = $main::SDXRoot . "\\" . @$projectandroot[1];
  3000. $sdini = $fullprojectroot . "\\sd.ini";
  3001. (-e $sdini) or (print "$header\nCan't find $sdini.\n\nRun 'sdx repair $main::SDMapCodeBase $main::SDMapBranch' to restore it.\n" and next);
  3002. chdir $fullprojectroot or die("\nCan't cd to $fullprojectroot.\n");
  3003. $main::V2 and do
  3004. {
  3005. print "project root = '$fullprojectroot'\n";
  3006. };
  3007. #
  3008. # enumdepots -- internal -- collects server:ports in use
  3009. #
  3010. $defcmd eq "enumdepots" and do
  3011. {
  3012. SDX::EnumDepots($userargs, $project, $sdini);
  3013. next;
  3014. };
  3015. #
  3016. # files -- count depot files in chunks
  3017. #
  3018. $defcmd eq "files" and do
  3019. {
  3020. SDX::Files($userargs, $project, $header);
  3021. next;
  3022. };
  3023. #
  3024. # projects -- list enlisted projects and their roots
  3025. #
  3026. $defcmd eq "projects" and do
  3027. {
  3028. SDX::ListProjects($userargs, $project, $header);
  3029. next;
  3030. };
  3031. #
  3032. # status is a combination of opened and sync -n
  3033. #
  3034. $defcmd eq "status" and do
  3035. {
  3036. SDX::Status($userargs, $project, $header, $cmdtype);
  3037. next;
  3038. };
  3039. #
  3040. # special-case lab branches only if creating one
  3041. #
  3042. $labbranch and do
  3043. {
  3044. SDX::LabBranch($userargs, $project, $header, "modify", $cmdtype);
  3045. next;
  3046. };
  3047. #
  3048. # handle private branches
  3049. #
  3050. $privatebranch and do
  3051. {
  3052. SDX::PrivateBranch($userargs, $project, $header, "modify", $cmdtype);
  3053. next;
  3054. };
  3055. #
  3056. # opened may need special handling
  3057. #
  3058. $defcmd eq "opened" and do
  3059. {
  3060. SDX::Opened($userargs, $project, $header, $cmdtype);
  3061. next;
  3062. };
  3063. #
  3064. # resolve -am needs special handling
  3065. #
  3066. $defcmd eq "resolve" and do
  3067. {
  3068. SDX::Resolve($userargs, $project, $header, $cmdtype);
  3069. next;
  3070. };
  3071. #
  3072. # submit may be using a comment from the cmd line
  3073. #
  3074. $defcmd eq "submit" and do
  3075. {
  3076. SDX::Submit($userargs, $project, $header, $cmdtype);
  3077. next;
  3078. };
  3079. #
  3080. # sync/flush may need the -q(uiet) flag
  3081. #
  3082. ($defcmd eq "sync" or $defcmd eq "flush") and do
  3083. {
  3084. SDX::SyncFlush($defcmd, $userargs, $project, $header, $cmdtype);
  3085. next;
  3086. };
  3087. #
  3088. # it's none of the above, so print or run the final cmd string
  3089. #
  3090. $fullcmd = "sd.exe $cmd 2>&1";
  3091. SDX::RunSDCmd($header, $fullcmd);
  3092. }
  3093. };
  3094. #
  3095. # for type 2 commands, where the cmd makes sense only at the depot level, loop
  3096. # through the depot list and run $defcmd
  3097. #
  3098. # type 2 commands only exist when the depot structure is type 2, where N projects
  3099. # exist per depot
  3100. #
  3101. $cmdtype == 2 and do
  3102. {
  3103. #
  3104. # for type 2 commands read the codebase map
  3105. # and figure out the depot type
  3106. #
  3107. SDX::GetDepotTypes();
  3108. #
  3109. # run the cmd on each depot
  3110. #
  3111. foreach $serverport (@main::SDMapDepots)
  3112. {
  3113. #
  3114. # for type 1 depots, get the project name
  3115. #
  3116. $project = (@{$main::DepotType{$serverport}}[0] == 1) ? "@{$main::DepotType{$serverport}}[1]\n" : "$serverport [MULTIPROJECT DEPOT]\n";
  3117. chop $project;
  3118. #
  3119. # header depends on depot type
  3120. #
  3121. # for type 1, show the project name
  3122. # for type 2, show the server:port
  3123. #
  3124. $header = "\n---------------- ";
  3125. $header .= "\U$project\n";
  3126. #
  3127. # skip this depot if it's type 1 and the user negated it on the cmd line with '~project'
  3128. #
  3129. $fulluserargs =~ /~$project / and next;
  3130. #
  3131. # special-case lab branches only if creating one
  3132. #
  3133. $labbranch and do
  3134. {
  3135. SDX::LabBranch($userargs, $serverport, $header, "modify", $cmdtype);
  3136. next;
  3137. };
  3138. #
  3139. # handle private branches
  3140. #
  3141. $privatebranch and do
  3142. {
  3143. SDX::PrivateBranch($userargs, $serverport, $header, "modify", $cmdtype);
  3144. next;
  3145. };
  3146. #
  3147. # opened may need special handling
  3148. #
  3149. $defcmd eq "opened" and do
  3150. {
  3151. SDX::Opened($userargs, $serverport, $header, $cmdtype);
  3152. next;
  3153. };
  3154. #
  3155. # resolve -am needs special handling
  3156. #
  3157. $defcmd eq "resolve" and do
  3158. {
  3159. SDX::Resolve($userargs, $serverport, $header, $cmdtype);
  3160. next;
  3161. };
  3162. #
  3163. # submit may be using a comment from the cmd line
  3164. #
  3165. $defcmd eq "submit" and do
  3166. {
  3167. SDX::Submit($userargs, $serverport, $header, $cmdtype);
  3168. next;
  3169. };
  3170. #
  3171. # sync/flush may need the -q(uiet) flag
  3172. #
  3173. ($defcmd eq "sync" or $defcmd eq "flush") and do
  3174. {
  3175. SDX::SyncFlush($defcmd, $userargs, $serverport, $header, $cmdtype);
  3176. next;
  3177. };
  3178. #
  3179. # it's none of the above, so print or run the final cmd string
  3180. #
  3181. $fullcmd = "sd.exe -p $serverport $cmd 2>&1";
  3182. SDX::RunSDCmd($header, $fullcmd);
  3183. }
  3184. };
  3185. #
  3186. # if we just branched, give the user some instructions
  3187. #
  3188. $privatebranch and SDX::PrivateBranch($userargs, $main::Null, $main::Null, "end");
  3189. $labbranch and SDX::LabBranch($userargs, $main::Null, $main::Null, "end");
  3190. #
  3191. # print a file counter summary
  3192. #
  3193. SDX::PrintStats($defcmd, $userargs);
  3194. #
  3195. # success
  3196. #
  3197. return 0;
  3198. }
  3199. # _____________________________________________________________________________
  3200. #
  3201. # Delta
  3202. # called from sdx.pl to calculate the changes in a given project
  3203. #
  3204. # Parameters:
  3205. # $fulluserargs -- all args as passed in
  3206. #
  3207. # Output:
  3208. # _____________________________________________________________________________
  3209. sub Delta
  3210. {
  3211. local $base_change, $current_change;
  3212. local %baseline;
  3213. my $fulluserargs = $_[1];
  3214. my $cmd = "";
  3215. my $project = "";
  3216. my $string = "";
  3217. my $generate = 0;
  3218. if($fulluserargs) {
  3219. $fulluserargs =~ s/^\s+(.*)/$1/;
  3220. }
  3221. if($fulluserargs) {
  3222. @args = split /\s+/, $fulluserargs;
  3223. $generate = 0;
  3224. print "Checking for differences from baseline change number(s):\n";
  3225. } else {
  3226. $generate = 1;
  3227. }
  3228. #
  3229. # parse the arguments to get the base change number for each project.
  3230. #
  3231. foreach $entry (@args) {
  3232. ($project, $change) = split /=/, $entry;
  3233. $baseline{$project} = $change;
  3234. }
  3235. #
  3236. # maybe delete previous log
  3237. #
  3238. $main::Logging and unlink $main::Log;
  3239. #
  3240. # for type 1 commands, where the scope as it appears to the user is per-
  3241. # project, loop through the project list and run $defcmd
  3242. #
  3243. # note that for type 1 codebases (with one project per depot), all commands
  3244. # are essentially type 1
  3245. #
  3246. #
  3247. # for each project, change to it's root and run $defcmd
  3248. #
  3249. foreach $projectandroot (@main::SDMapProjects)
  3250. {
  3251. $project = @$projectandroot[0];
  3252. #if(($generate == 0) && (!defined($baseline{$project}))) {
  3253. # print "no baseline for $project\n";
  3254. # next;
  3255. #}
  3256. #
  3257. # get path to SD.INI, make sure we have it, and cd there
  3258. #
  3259. $fullprojectroot = $main::SDXRoot . "\\" . @$projectandroot[1];
  3260. $sdini = $fullprojectroot . "\\sd.ini";
  3261. (-e $sdini) or (print "$header\nCan't find $sdini.\n\nRun 'sdx repair $main::SDMapCodeBase $main::SDMapBranch' to restore it.\n" and next);
  3262. chdir $fullprojectroot or die("\nCan't cd to $fullprojectroot.\n");
  3263. #
  3264. # Find out what the most recent change in this project is.
  3265. #
  3266. open FILE, "sd.exe changes -m 1 ...#have 2>&1|" or die("\nDelta: can't open pipe for $string\n");
  3267. my $line = <FILE>;
  3268. close FILE;
  3269. if($line =~ /Change ([0-9]+)/) {
  3270. $current_change = $1;
  3271. } else {
  3272. print "Error retrieving change: $line\n" if ($baseline);
  3273. next;
  3274. }
  3275. #
  3276. # if we have no baseline changes to compare against then just generate
  3277. # a command line which could be passed in later.
  3278. #
  3279. if($generate == 1) {
  3280. print "$project=$current_change ";
  3281. next;
  3282. }
  3283. print "$project: ";
  3284. #
  3285. # now check to see if we have an entry for this project in the
  3286. # baseline passed in.
  3287. #
  3288. $base_change = $baseline{$project};
  3289. #print "$baseline{$project} = $base_change\n";
  3290. if (!defined($base_change)) {
  3291. print "at change $current_change (no previous change # provided)\n";
  3292. next;
  3293. }
  3294. if ($base_change == $current_change) {
  3295. print "at original change $current_change\n";
  3296. next;
  3297. }
  3298. if ($base_change > $current_change) {
  3299. print "reverted from change $base_change to $current_change\n";
  3300. next;
  3301. }
  3302. #
  3303. # the current highest change number is > than the one in the baseline
  3304. # passed in. Try to determine which changes (if any) have been picked
  3305. # up.
  3306. #
  3307. #
  3308. # first check to see if we're just sunk to the new change number.
  3309. # do this by syncing to it again (-n). If no new files would be
  3310. # picked up then we're done.
  3311. #
  3312. $string = "sd.exe sync -n \@$current_change 2>&1|";
  3313. #print "$string\n";
  3314. open FILE, $string or die("\nCan't open pipe for $string\n");
  3315. $change_line = <FILE>;
  3316. close FILE;
  3317. #print "change_line = $change_line\n";
  3318. #print "substr = *", substr($change_line, 0, 1), "*\n";
  3319. if(substr($change_line, 0, 1) eq "@") {
  3320. print "updated from change $base_change to $current_change\n";
  3321. next;
  3322. }
  3323. #
  3324. # no such luck.
  3325. # get a list of all the files which are different (by syncing to the
  3326. # baseline change number) and print them out grouped by change number.
  3327. #
  3328. print "has files between change $base_change and $current_change (listing follows):\n";
  3329. $string = "sd.exe sync -n ...\@$base_change 2>&1|";
  3330. #print "$string\n";
  3331. open FILE, $string or die("\nDelta: can't open pipe for $string\n");
  3332. foreach $change_line (<FILE>) {
  3333. #print "raw: $change_line\n";
  3334. if(substr($change_line, 0, 2) != "//") {
  3335. print "error of some form\n";
  3336. last;
  3337. }
  3338. @t = split /\#/, $change_line;
  3339. #print "chopped: $t[0]\n";
  3340. $string = "sd.exe have $t[0] 2>&1|";
  3341. #print "$string\n";
  3342. open FILE2, $string or die("\nDelta: can't open pipe for $string\n");
  3343. $line = <FILE2>;
  3344. close FILE2;
  3345. @t = split / - /, $line;
  3346. print "\t$t[0]\n";
  3347. }
  3348. close FILE;
  3349. }
  3350. print "\n";
  3351. }
  3352. # _____________________________________________________________________________
  3353. #
  3354. # RunSDCmd
  3355. #
  3356. # Print the header, then print or call the SD cmd
  3357. #
  3358. # Parameters:
  3359. # $string user output
  3360. #
  3361. # Output:
  3362. # _____________________________________________________________________________
  3363. sub RunSDCmd
  3364. {
  3365. my $header = $_[0];
  3366. my $fullcmd = $_[1];
  3367. #
  3368. # print the header
  3369. #
  3370. SDX::PrintCmd($header, 0);
  3371. #
  3372. # print or run the cmd
  3373. #
  3374. if ($main::V2)
  3375. {
  3376. SDX::PrintCmd($fullcmd, 1);
  3377. }
  3378. else
  3379. {
  3380. SDX::RunCmd($fullcmd);
  3381. }
  3382. }
  3383. # _____________________________________________________________________________
  3384. #
  3385. # PrintCmd
  3386. #
  3387. # Print cmd header or string
  3388. #
  3389. # Parameters:
  3390. # $string user output
  3391. # $op 0 - header, 1 - cmd
  3392. #
  3393. # Output:
  3394. # _____________________________________________________________________________
  3395. sub PrintCmd
  3396. {
  3397. my $string = $_[0];
  3398. my $op = $_[1];
  3399. $main::Logging and (open LOG, ">>$main::Log" or die("\nCan't append $main::Log.\n"));
  3400. $op == 0 and do
  3401. {
  3402. print "$string";
  3403. $main::Logging and print LOG "$string";
  3404. };
  3405. $op == 1 and do
  3406. {
  3407. print "`$string`\n";
  3408. $main::Logging and print LOG "`$string`\n";
  3409. };
  3410. $main::Logging and close LOG;
  3411. }
  3412. # _____________________________________________________________________________
  3413. #
  3414. # RunCmd
  3415. #
  3416. # Run the given SD cmd, capturing the output, and maybe printing it to STDERR
  3417. #
  3418. # Parameters:
  3419. # $string user output
  3420. #
  3421. # Output:
  3422. # _____________________________________________________________________________
  3423. sub RunCmd
  3424. {
  3425. my $string = $_[0];
  3426. my $out = "";
  3427. my $resolved = ($string =~ / resolved /);
  3428. my $mergefile = "";
  3429. my @list = ();
  3430. !$string and die("\nNo command string in RunCmd.\n");
  3431. my $skippublic = 0;
  3432. #
  3433. # if NT, if not using -a, and if not verbose, filter out changes associated
  3434. # with the public change number
  3435. #
  3436. ("\U$main::CodeBase" eq "NT" and ($main::UserArgs !~ /-a/) and ($main::PublicChangeNum and !$main::MinusV)) and do
  3437. {
  3438. $skippublic++;
  3439. };
  3440. #
  3441. # special-case sdx {clients|users} -t and -a
  3442. # set flags, maybe remove -t from cmd string
  3443. #
  3444. my $fa = ($string =~ / files / and $main::MinusA);
  3445. my $ca = ($string =~ / clients / and $main::MinusA);
  3446. my $ua = ($string =~ / users / and $main::MinusA);
  3447. my $ct = ($string =~ / clients / and $string =~ / -t /);
  3448. my $ut = ($string =~ / users / and $string =~ / -t /);
  3449. $ct and $string =~ s/-t//g;
  3450. $ut and $string =~ s/-t//g;
  3451. #
  3452. # run the cmd
  3453. #
  3454. # for commands like manual resolve that need user input, run them with the shell
  3455. #
  3456. if ($string =~ / resolve / and $string !~ /-a[tymf]*|-n/)
  3457. {
  3458. system "$string";
  3459. }
  3460. elsif ($main::MinusI and !$main::MinusH)
  3461. {
  3462. #
  3463. # write the input form to stdin
  3464. #
  3465. # no logging for now
  3466. #
  3467. open FILE, "| $string" or die("\nRunCMD: can't open pipe for $string.\n");
  3468. foreach (@main::InputForm) { print FILE "$_"; }
  3469. close FILE;
  3470. }
  3471. else
  3472. {
  3473. $main::Logging and (open LOG, ">>$main::Log" or die("\nCan't append $main::LOG\n"));
  3474. #
  3475. # run cmd unless sdx files -a
  3476. #
  3477. (!$fa) and do
  3478. {
  3479. open FILE, "$string |" or die("\nRunCMD: can't open pipe for $string\n");
  3480. };
  3481. my $quiet = $main::Quiet;
  3482. while (<FILE>)
  3483. {
  3484. #
  3485. # be noisy as soon as we see an SD error
  3486. #
  3487. / error:/ and do
  3488. {
  3489. $main::Quiet = $main::FALSE;
  3490. $main::DepotErrors++;
  3491. };
  3492. #
  3493. # if skipping public changes, maybe skip this line
  3494. #
  3495. ($skippublic and / change $main::PublicChangeNum/) and do
  3496. {
  3497. next;
  3498. };
  3499. #
  3500. # if sdx {clients|users} -a, save for later
  3501. #
  3502. ($ca or $ua) and do
  3503. {
  3504. push @list, $_;
  3505. next;
  3506. };
  3507. #
  3508. # reformat for sdx {clients|users} -t and save for sorting later
  3509. #
  3510. ($ct or $ut) and do
  3511. {
  3512. chop $_;
  3513. #
  3514. # remove friendly user name before splitting
  3515. #
  3516. $ut and $_ =~ s/\([_\. $A-Za-z0-9\\-]*\)//g;
  3517. @fields = split(/ /, $_);
  3518. $ct and do
  3519. {
  3520. my $u = @fields[$#fields-1];
  3521. $u =~ s/\.$//g;
  3522. push @list, sprintf("%s:%s %-20s %-20s %s\n", @fields[2], @fields[3], @fields[1], $u, @fields[5]);
  3523. };
  3524. $ut and push @list, sprintf("%s:%s %-20s\n", @fields[4], @fields[5], @fields[0]);
  3525. next;
  3526. };
  3527. #
  3528. # show results
  3529. #
  3530. # not logging, not quiet -- print to stdout
  3531. # not logging, quiet -- do not print to stdout
  3532. # logging, not quiet -- print to log
  3533. # logging, quiet -- print to log
  3534. #
  3535. #
  3536. # -q on sd <command> -o throws away only comment lines
  3537. #
  3538. ($main::Quiet and $main::MinusO and /#/) and next;
  3539. #
  3540. # show progress on stdout if not quiet
  3541. # or show on stdout if quiet but sd cmd includes -o
  3542. #
  3543. (!$main::Quiet or ($main::Quiet and $main::MinusO)) and print;
  3544. #
  3545. # maybe log output
  3546. #
  3547. $main::Logging and print LOG;
  3548. #
  3549. # keep some stats
  3550. #
  3551. ($resolved and / - /) and $main::FilesResolved++;
  3552. / - branch\/sync from / and $main::IntFilesAdded++;
  3553. / - branch from / and $main::IntFilesAdded++;
  3554. / - delete from / and $main::IntFilesDeleted++;
  3555. / - sync\/integrate from / and $main::IntFilesChanged++;
  3556. / - integrate from / and $main::IntFilesChanged++;
  3557. / - updating / and $main::FilesUpdated++;
  3558. / - updated/ and $main::LabelFilesUpdated++;
  3559. / - add / and $main::FilesOpenAdd++;
  3560. / - delete / and $main::FilesOpenDelete++;
  3561. / - edit / and $main::FilesOpenEdit++;
  3562. / - added / and $main::FilesAdded++;
  3563. / - added/ and $main::LabelFilesAdded++;
  3564. / - deleted / and $main::FilesDeleted++;
  3565. / - deleted/ and $main::LabelFilesDeleted++;
  3566. / - merging | - vs / and do
  3567. {
  3568. $main::FilesToMerge++;
  3569. $mergefile = $_;
  3570. };
  3571. / - must resolve / and $main::FilesToResolve++;
  3572. / - resolve skipped/ and $main::FilesSkipped++;
  3573. / [1-9][0-9]* conflicting/ and do
  3574. {
  3575. $main::FilesConflicting++;
  3576. push @main::ConflictingFiles, $mergefile;
  3577. $mergefile = "";
  3578. };
  3579. / 0 conflicting| - copy from / and $main::FilesNotConflicting++;
  3580. / clobber / and $main::FilesNotClobbered++;
  3581. / reverted/ and $main::FilesReverted++;
  3582. ### submits don't come through this block
  3583. ### / - already locked / and $main::FilesLocked++;
  3584. ### /Submit failed / and $main::FailedSubmits++;
  3585. }
  3586. #
  3587. # keep track of catastrophic sd.exe errors
  3588. #
  3589. close FILE or $main::DepotErrors++;
  3590. #
  3591. # sort and print
  3592. #
  3593. ($ct or $ut) and do
  3594. {
  3595. @list = sort @list;
  3596. for (@list)
  3597. {
  3598. #
  3599. # show progress on stdout if not quiet
  3600. #
  3601. (!$main::Quiet) and print;
  3602. #
  3603. # maybe log output
  3604. #
  3605. $main::Logging and print LOG;
  3606. }
  3607. my $s = "\nTotal:\t$#list\n";
  3608. !$main::Quiet and print $s;
  3609. $main::Logging and print LOG $s;
  3610. };
  3611. #
  3612. # print totals for client/user counts
  3613. #
  3614. ($ca or $ua) and do
  3615. {
  3616. !$main::Quiet and print "\nTotal:\t$#list\n";
  3617. $main::Logging and print LOG "\nTotal:\t$#list\n";
  3618. };
  3619. #
  3620. # print totals for file counts
  3621. #
  3622. ($fa) and do
  3623. {
  3624. foreach (@main::FileChunks)
  3625. {
  3626. #
  3627. # show progress on stdout if not quiet
  3628. #
  3629. !$main::Quiet and print "$_\n";
  3630. #
  3631. # maybe log output
  3632. #
  3633. $main::Logging and print LOG "$_\n";
  3634. }
  3635. my $s = sprintf "%53s\nTotal:%47s\n", "=======", $main::DepotFiles;
  3636. !$main::Quiet and print $s;
  3637. $main::Logging and printf LOG $s;
  3638. };
  3639. $main::Logging and close LOG;
  3640. #
  3641. # maybe restore quiet mode for next SD call
  3642. #
  3643. $main::Quiet = $quiet;
  3644. }
  3645. }
  3646. # _____________________________________________________________________________
  3647. #
  3648. # PrintStats
  3649. #
  3650. # Dump the file counters
  3651. #
  3652. # Parameters:
  3653. #
  3654. # Output:
  3655. # _____________________________________________________________________________
  3656. sub PrintStats
  3657. {
  3658. my $defcmd = $_[0];
  3659. my $userargs = $_[1];
  3660. my $syncresolve = $main::FALSE;
  3661. my @counters = ("\n\n\n");
  3662. $userargs =~ /-a[fm]/ and $syncresolve = $main::TRUE;
  3663. $defcmd eq "integrate" and do
  3664. {
  3665. push @counters, sprintf "== Summary ==========\n";
  3666. push @counters, sprintf "\nAdded:%15s\n", $main::IntFilesAdded;
  3667. push @counters, sprintf "Deleted:%13s\n", $main::IntFilesDeleted;
  3668. push @counters, sprintf "Integrated:%10s\n", $main::IntFilesChanged;
  3669. push @counters, sprintf "\nTotal:%15s\n", $main::IntFilesAdded + $main::IntFilesDeleted + $main::IntFilesChanged;
  3670. #
  3671. # call out fatal SD client errors
  3672. #
  3673. my $pad = sprintf "$spacer%3s", "";
  3674. $main::DepotErrors and SDX::DepotErrors(\@counters, $pad, $main::DepotErrors);
  3675. push @counters, sprintf "=====================\n";
  3676. };
  3677. ($defcmd eq "sync" or $defcmd eq "flush") and do
  3678. {
  3679. my $header = "== Summary =========";
  3680. my $footer = "====================";
  3681. my $spacer = "";
  3682. $main::MinusH and do
  3683. {
  3684. $header .= "==============";
  3685. $spacer = " ";
  3686. };
  3687. #
  3688. # adjust update total
  3689. #
  3690. ($main::FilesUpdated >= $main::FilesNotClobbered) and $main::FilesUpdated -= $main::FilesNotClobbered;
  3691. #
  3692. # print file stats
  3693. #
  3694. push @counters, sprintf "%s%s\n", $header, ($main::FilesSkipped or $main::FilesConflicting) ? "==========================================================" : "";
  3695. push @counters, sprintf "\nUpdated:%s%12s\n", $spacer, $main::FilesUpdated;
  3696. $main::FilesNotClobbered and push @counters, sprintf "Not Updated:%s%8s\n", $spacer, $main::FilesNotClobbered;
  3697. push @counters, sprintf "Added:%s%14s\n", $spacer, $main::FilesAdded;
  3698. push @counters, sprintf "Deleted:%s%12s\n", $spacer, $main::FilesDeleted;
  3699. #
  3700. # if no resolve use one resolve counter
  3701. #
  3702. (!$syncresolve and $main::FilesToResolve) and push @counters, sprintf "\nTo Resolve:%s%9s\n", $spacer, $main::FilesToResolve;
  3703. #
  3704. # else use others
  3705. #
  3706. $syncresolve and do
  3707. {
  3708. $main::FilesNotConflicting and push @counters, sprintf "Resolved:%s%11s\n", $spacer, $main::FilesNotConflicting;
  3709. $main::FilesSkipped and push @counters, sprintf "\nSkipped:%s%12s\n", $spacer, $main::FilesSkipped;
  3710. (!$main::FilesSkipped and $main::FilesConflicting) and push @counters, sprintf "\nConflicting:%s%8s\n", $spacer, $main::FilesConflicting;
  3711. };
  3712. #
  3713. # total count depends on whether we resolved
  3714. #
  3715. my $total = $main::FilesUpdated + $main::FilesNotClobbered + $main::FilesAdded + $main::FilesDeleted;
  3716. if ($syncresolve)
  3717. {
  3718. $total += $main::FilesNotConflicting;
  3719. $total += ($main::FileSkipped) ? $main::FilesSkipped : $main::FilesConflicting;
  3720. }
  3721. else
  3722. {
  3723. $total += $main::FilesToResolve;
  3724. }
  3725. push @counters, sprintf "\nTotal:%s%14s\n", $spacer, $total;
  3726. #
  3727. # call out fatal SD client errors
  3728. #
  3729. my $pad = sprintf "$spacer%2s", "";
  3730. $main::DepotErrors and SDX::DepotErrors(\@counters, $pad, $main::DepotErrors);
  3731. #
  3732. # call out resolve problems
  3733. #
  3734. ($main::FilesSkipped or $main::FilesConflicting) and do
  3735. {
  3736. if ($main::FilesSkipped)
  3737. {
  3738. push @counters, sprintf "\n\nSkipped Files [resolve manually]\n\n";
  3739. }
  3740. else
  3741. {
  3742. push @counters, sprintf "\n\nConflicting Files [edit and fix merge conflicts]\n\n";
  3743. }
  3744. foreach $file (@main::ConflictingFiles)
  3745. {
  3746. @fields = split(/ /,$file);
  3747. push @counters, sprintf "@fields[1]\n";
  3748. }
  3749. };
  3750. #
  3751. # if sync/flush is tracking changelists, print change stats
  3752. #
  3753. ($main::MinusH) and do
  3754. {
  3755. my $total = $main::Changes;
  3756. push @counters, sprintf "\nChanges in this branch:%11s\n", $main::Changes;
  3757. $main::MinusI and do
  3758. {
  3759. push @counters, sprintf "Changes in other branches:%8s\n", $main::IntegrationChanges;
  3760. $total += $main::IntegrationChanges;
  3761. };
  3762. push @counters, sprintf "\nTotal:%28s\n", $total;
  3763. $footer .= "==============";
  3764. };
  3765. push @counters, sprintf "%s%s\n", $footer, ($main::FilesSkipped or $main::FilesConflicting) ? "==========================================================" : "";
  3766. };
  3767. $defcmd eq "opened" and do
  3768. {
  3769. push @counters, sprintf "== Summary =============\n";
  3770. push @counters, sprintf "\nOpen for Add:%11s\n", $main::FilesOpenAdd;
  3771. push @counters, sprintf "Open for Edit:%10s\n", $main::FilesOpenEdit;
  3772. push @counters, sprintf "Open for Delete:%8s\n", $main::FilesOpenDelete;
  3773. push @counters, sprintf "\nTotal:%18s\n", $main::FilesOpenAdd + $main::FilesOpenDelete + $main::FilesOpenEdit;
  3774. #
  3775. # call out fatal SD client errors
  3776. #
  3777. my $pad = sprintf "%6s", "";
  3778. $main::DepotErrors and SDX::DepotErrors(\@counters, $pad, $main::DepotErrors);
  3779. push @counters, sprintf "========================\n";
  3780. };
  3781. $defcmd eq "labelsync" and do
  3782. {
  3783. push @counters, sprintf "== Summary =========\n";
  3784. push @counters, sprintf "\nAdded:%14s\n", $main::LabelFilesAdded;
  3785. push @counters, sprintf "Deleted:%12s\n", $main::LabelFilesDeleted;
  3786. push @counters, sprintf "Updated:%12s\n", $main::LabelFilesUpdated;
  3787. push @counters, sprintf "\nTotal:%14s\n", $main::LabelFilesAdded + $main::LabelFilesDeleted + $main::LabelFilesUpdated;
  3788. #
  3789. # call out fatal SD client errors
  3790. #
  3791. my $pad = sprintf "%2s", "";
  3792. $main::DepotErrors and SDX::DepotErrors(\@counters, $pad, $main::DepotErrors);
  3793. push @counters, sprintf "====================\n";
  3794. };
  3795. $defcmd eq "resolve" and do
  3796. {
  3797. push @counters, sprintf "== Summary ===========\n";
  3798. if ($userargs =~ /-n/)
  3799. {
  3800. push @counters, sprintf "\nTo Resolve:%11s\n", $main::FilesToMerge;
  3801. }
  3802. else
  3803. {
  3804. push @counters, sprintf "\nResolved:%13s\n", $main::FilesNotConflicting;
  3805. $main::FilesSkipped and push @counters, sprintf "Skipped:%14s\n", $main::FilesSkipped;
  3806. (!$main::FilesSkipped and $main::FilesConflicting) and push @counters, sprintf "Conflicting:%10s\n", $main::FilesConflicting;
  3807. my $total = $main::FilesNotConflicting;
  3808. $total += ($main::FileSkipped) ? $main::FilesSkipped : $main::FilesConflicting;
  3809. push @counters, sprintf "\nTotal:%16s\n", $total;
  3810. }
  3811. #
  3812. # call out fatal SD client errors
  3813. #
  3814. my $pad = sprintf "%4s", "";
  3815. $main::DepotErrors and SDX::DepotErrors(\@counters, $pad, $main::DepotErrors);
  3816. push @counters, sprintf "======================\n";
  3817. };
  3818. $defcmd eq "resolved" and do
  3819. {
  3820. push @counters, sprintf "== Summary ===========\n";
  3821. push @counters, sprintf "\nResolved:%13s\n", $main::FilesResolved;
  3822. #
  3823. # call out fatal SD client errors
  3824. #
  3825. my $pad = sprintf "%4s", "";
  3826. $main::DepotErrors and SDX::DepotErrors(\@counters, $pad, $main::DepotErrors);
  3827. push @counters, sprintf "======================\n";
  3828. };
  3829. $defcmd eq "revert" and do
  3830. {
  3831. push @counters, sprintf "== Summary ===========\n";
  3832. push @counters, sprintf "\nReverted:%13s\n", $main::FilesReverted;
  3833. #
  3834. # call out fatal SD client errors
  3835. #
  3836. my $pad = sprintf "%4s", "";
  3837. $main::DepotErrors and SDX::DepotErrors(\@counters, $pad, $main::DepotErrors);
  3838. push @counters, sprintf "======================\n";
  3839. };
  3840. =begin comment text
  3841. $defcmd eq "submit" and do
  3842. {
  3843. push @counters, sprintf "== Summary ===========\n";
  3844. $main::FailedSubmits and do
  3845. {
  3846. push @counters, sprintf "\nFailed Submits:%8s\n", $main::FailedSubmits;
  3847. push @counters, sprintf "\nFiles Locked by Others:%8s\n", $main::FilesLocked;
  3848. };
  3849. #
  3850. # call out fatal SD client errors
  3851. #
  3852. my $pad = sprintf "%4s", "";
  3853. $main::DepotErrors and SDX::DepotErrors(\@counters, $pad, $main::DepotErrors);
  3854. push @counters, sprintf "======================\n";
  3855. };
  3856. =end comment text
  3857. =cut
  3858. #
  3859. # print to stdout and maybe to the log file
  3860. # print the stats except in extra-quiet mode
  3861. #
  3862. foreach (@counters) { print; }
  3863. $main::Logging and do
  3864. {
  3865. open LOG, ">>$main::Log" or die("\nCan't append $main::LOG\n");
  3866. foreach (@counters) { print LOG; }
  3867. close LOG;
  3868. };
  3869. }
  3870. # _____________________________________________________________________________
  3871. #
  3872. # LabBranch
  3873. #
  3874. # called from OtherOp() to create a single high-level branch in the current
  3875. # project or depot
  3876. #
  3877. # Parameters:
  3878. # $labbranch branch name
  3879. # $spproject server:port if cmd type 2, project name if type 1
  3880. # $header user output
  3881. # Output:
  3882. # _____________________________________________________________________________
  3883. sub LabBranch
  3884. {
  3885. my $labbranch = "\L$_[0]";
  3886. my $spproject = $_[1];
  3887. my $header = $_[2];
  3888. my $op = $_[3];
  3889. my $cmdtype = $_[4];
  3890. my $branchview = "$ENV{TMP}\\branchview";
  3891. my $fullcmd = "";
  3892. #
  3893. # trim out ws
  3894. #
  3895. $labbranch =~ s/[\t\s]*//g;
  3896. !$labbranch and die("\nMissing branch name. Run 'sdx labbranch /?' for more information.\n");
  3897. $main::V2 and do
  3898. {
  3899. print "\n\n\nbranch = '$labbranch'\n";
  3900. print "spproject = '$spproject'\n";
  3901. };
  3902. #
  3903. # branch can't be Main
  3904. #
  3905. $labbranch eq "main" and die("\n'Main' is a reserved branch name.\n");
  3906. #
  3907. # print lab dev branch instructions
  3908. #
  3909. $op eq "start" and do
  3910. {
  3911. printf "\n\nThis script will create virtual lab branch %s.\n", "\U$labbranch";
  3912. if ($cmdtype == 1)
  3913. {
  3914. printf "\nIf %s is a new branch, for each project you are enlisted in, a branch\n", "\U$labbranch";
  3915. print "view of\n";
  3916. print "\n //depot/main/<project>/... //depot/$labbranch/<project>/...\n";
  3917. print "\nwill be used to map files into the branch.\n";
  3918. printf "\nIf %s exists, you can edit its view to add or remove directories and files.\n", "\U$labbranch";
  3919. print "\nYou can then integrate changes into the branch.\n";
  3920. }
  3921. else
  3922. {
  3923. print "\nLab branching is under construction for N:1 depots.\n";
  3924. }
  3925. print "\n\nIF YOU ARE NOT READY TO BRANCH, HIT CTRL-BREAK NOW.\n";
  3926. print " ==================\n\n\n";
  3927. print "Otherwise,\n\n";
  3928. system "pause";
  3929. print "\n\n";
  3930. };
  3931. #
  3932. # create branch in this project or depot
  3933. #
  3934. # called from loop in OtherOp
  3935. #
  3936. $op eq "modify" and do
  3937. {
  3938. #
  3939. # maybe use server:port
  3940. #
  3941. my $sp = SDX::ServerPort($cmdtype, $spproject);
  3942. #
  3943. # if the branch already exists, the user just wants to modify it, so
  3944. # give them the UI
  3945. # else
  3946. # create the default branch spec
  3947. #
  3948. if (SDX::BranchExists($labbranch, $sp, "", "by-name"))
  3949. {
  3950. my $fullcmd = "sd.exe $sp branch $labbranch";
  3951. $header .= "Updating branch $labbranch...\n";
  3952. SDX::RunSDCmd($header, $fullcmd);
  3953. }
  3954. else
  3955. {
  3956. $main::CreatingBranch = $main::TRUE;
  3957. #
  3958. # create default spec
  3959. #
  3960. SDX::WriteDefaultBranch($spproject, $labbranch, $header, $sp, "lab");
  3961. }
  3962. };
  3963. #
  3964. # give the user instructions for adding the branch to their client view
  3965. #
  3966. $op eq "end" and do
  3967. {
  3968. print "\n\n\nDone.\n";
  3969. printf "\nTo use %s, you must:\n", "\U$labbranch";
  3970. print "\n 1. Populate the tools in the Root project\n";
  3971. print "\n 2. Enlist in the branch\n";
  3972. print "\n 3. Integrate changes to it and resolve merge conflicts\n";
  3973. print "\n 4. Submit your changes\n";
  3974. };
  3975. }
  3976. # _____________________________________________________________________________
  3977. #
  3978. # PrivateBranch
  3979. #
  3980. # called from OtherOp() to create a private dev branch in each enlisted
  3981. # project/depot
  3982. #
  3983. # Parameters:
  3984. # $labbranch branch name
  3985. # $spproject server:port if cmd type 2, project name if type 1
  3986. # $header user output
  3987. # Output:
  3988. # _____________________________________________________________________________
  3989. sub PrivateBranch
  3990. {
  3991. my $pbranch = "\L$_[0]";
  3992. my $spproject = $_[1];
  3993. my $header = $_[2];
  3994. my $op = $_[3];
  3995. my $cmdtype = $_[4];
  3996. #
  3997. # trim out ws
  3998. #
  3999. $pbranch =~ s/[\t\s]*//g;
  4000. !$pbranch and die("\nMissing branch name. Run 'sdx privatebranch /?' for more information.\n");
  4001. $main::V2 and do
  4002. {
  4003. print "\n\n\nbranch = '$pbranch'\n";
  4004. print "spproject = '$spproject'\n";
  4005. };
  4006. #
  4007. # branch can't be Main
  4008. #
  4009. $pbranch eq "main" and die("\n'Main' is a reserved branch name.\n");
  4010. #
  4011. # print private dev branch instructions
  4012. #
  4013. $op eq "start" and do
  4014. {
  4015. printf "\n\nThis script will create or update private development branch %s.\n", "\U$pbranch";
  4016. printf "\nIf %s is a new branch, for each %s you are enlisted in this will:\n", "\U$pbranch", $cmdtype == 1 ? "project" : "depot";
  4017. print "\n 1. Create a default branch view, with placeholders representing\n";
  4018. printf " your project %s\n", $cmdtype == 1 ? "" : "and component";
  4019. print "\n 2. Ask you to edit the view to include only those directories and\n";
  4020. print " files you need in the branch\n";
  4021. printf "\nIf %s exists, you can edit its view to add or remove directories and files.\n", "\U$pbranch";
  4022. print "\nYou can then add the branched files to your client view and integrate\n";
  4023. print "changes into the branch.\n";
  4024. printf "\n\nIF YOU ARE NOT READY TO BRANCH, HIT CTRL-BREAK NOW.\n";
  4025. printf " ==================\n\n\n";
  4026. print "Otherwise,\n\n";
  4027. system "pause";
  4028. print "\n\n";
  4029. };
  4030. #
  4031. # create branch in this project or depot
  4032. #
  4033. # called from loop in OtherOp
  4034. #
  4035. $op eq "modify" and do
  4036. {
  4037. #
  4038. # maybe use server:port
  4039. #
  4040. my $sp = SDX::ServerPort($cmdtype, $spproject);
  4041. #
  4042. # if the branch already exists, the user just wants to modify it, so
  4043. # give them the UI
  4044. # else
  4045. # create and register the default branch spec, then call branch again
  4046. # and let the user edit out the placeholders
  4047. #
  4048. if (SDX::BranchExists($pbranch, $sp, "", "by-name"))
  4049. {
  4050. my $fullcmd = "sd.exe $sp branch $pbranch";
  4051. $header .= "Updating branch $pbranch...\n";
  4052. SDX::RunSDCmd($header, $fullcmd);
  4053. }
  4054. else
  4055. {
  4056. $main::CreatingBranch = $main::TRUE;
  4057. #
  4058. # create default spec
  4059. #
  4060. SDX::WriteDefaultBranch($spproject, $pbranch, $header, $sp, "private");
  4061. #
  4062. # user must edit to remove the placeholders
  4063. #
  4064. SDX::EditBranch($sp, $pbranch);
  4065. }
  4066. };
  4067. #
  4068. # give the user instructions for adding the branch to their client view
  4069. #
  4070. $op eq "end" and do
  4071. {
  4072. print "\n\n\nDone.\n";
  4073. printf "\nTo use %s, you must:\n", "\U$pbranch";
  4074. print "\n 1. Modify your client view to include the branched files\n";
  4075. print "\n 2. Integrate changes to the branch and resolve merge conflicts\n";
  4076. print "\n 3. Submit your changes\n";
  4077. };
  4078. }
  4079. # _____________________________________________________________________________
  4080. #
  4081. # WriteDefaultBranch
  4082. #
  4083. # Parameters:
  4084. #
  4085. # Output:
  4086. #
  4087. # _____________________________________________________________________________
  4088. sub WriteDefaultBranch()
  4089. {
  4090. my $spproject = $_[0];
  4091. my $branch = $_[1];
  4092. my $header = $_[2];
  4093. my $sp = $_[3];
  4094. my $type = $_[4];
  4095. my $branchview = "$ENV{TMP}\\branchview";
  4096. my $fullcmd = "";
  4097. $type eq "lab" and do
  4098. {
  4099. #
  4100. # create branch spec
  4101. #
  4102. open(BRANCHVIEW, ">$branchview") or die("\nCan't open $branchview for writing.\n");
  4103. print BRANCHVIEW "Branch:\t$branch\n";
  4104. print BRANCHVIEW "Owner:\t$main::SDDomainUser\n";
  4105. print BRANCHVIEW "Description:\n\tLab or milestone branch created by $main::SDDomainUser.\n";
  4106. print BRANCHVIEW "View:\n";
  4107. #
  4108. # for type 1 depots, include the project name
  4109. #
  4110. if ($main::CodeBaseType == 1)
  4111. {
  4112. print BRANCHVIEW "\t//depot/main/$spproject/... //depot/$branch/$spproject/...\n";
  4113. }
  4114. else
  4115. {
  4116. print BRANCHVIEW "\t//depot/main/... //depot/$branch/...\n";
  4117. }
  4118. close(BRANCHVIEW);
  4119. };
  4120. $type eq "private" and do
  4121. {
  4122. #
  4123. # for type 1 depots we know the project
  4124. #
  4125. my $proj = ($main::CodeBaseType == 1 ? $spproject : "<<Your-Project>>");
  4126. open(BRANCHVIEW, ">$branchview") or die("\nCan't open $branchview for writing.\n");
  4127. print BRANCHVIEW "Branch:\t$branch\n";
  4128. print BRANCHVIEW "Owner:\t$main::SDDomainUser\n";
  4129. print BRANCHVIEW "Description:\n\tPrivate branch created by $main::SDDomainUser.\n";
  4130. print BRANCHVIEW "View:\n";
  4131. print BRANCHVIEW "\t//depot/$main::SDMapBranch/$proj/<<PATH>>/<<FILE1>> //depot/private/$main::SDUser/$proj/<<PATH>>/<<FILE1>>\n";
  4132. print BRANCHVIEW "\t//depot/$main::SDMapBranch/$proj/<<PATH>>/<<FILE2>> //depot/private/$main::SDUser/$proj/<<PATH>>/<<FILE2>>\n";
  4133. print BRANCHVIEW "\t//depot/$main::SDMapBranch/$proj/<<PATH>>/<<FILE3>> //depot/private/$main::SDUser/$proj/<<PATH>>/<<FILE3>>\n";
  4134. close(BRANCHVIEW);
  4135. };
  4136. #
  4137. # register the branch
  4138. #
  4139. $fullcmd = "sd.exe $sp branch -i < $branchview 2>&1";
  4140. $header .= "Creating branch \U$branch...\n";
  4141. SDX::RunSDCmd($header, $fullcmd);
  4142. }
  4143. # _____________________________________________________________________________
  4144. #
  4145. # EditBranch
  4146. #
  4147. # Parameters:
  4148. #
  4149. # Output:
  4150. #
  4151. # _____________________________________________________________________________
  4152. sub EditBranch()
  4153. {
  4154. my $sp = $_[0];
  4155. my $pbranch = $_[1];
  4156. my $found = $main::TRUE;
  4157. #
  4158. # let the user customize the spec
  4159. #
  4160. SDX::EditBranchSpec($sp, $pbranch);
  4161. #
  4162. # verify that the placeholders were removed
  4163. #
  4164. while ($found)
  4165. {
  4166. #
  4167. # dump the branch and look for telltale signs
  4168. #
  4169. ### @lines = `sd.exe $sp branch -o $pbranch`;
  4170. my $found2 = $main::FALSE;
  4171. grep(/<<|>>/, `sd.exe $sp branch -o $pbranch`) and $found2 = $main::TRUE;
  4172. #
  4173. # maybe edit again
  4174. #
  4175. $found2 and SDX::EditBranchSpec($sp, $pbranch);
  4176. #
  4177. # else we're done
  4178. #
  4179. !$found2 and $found = $main::FALSE;
  4180. }
  4181. }
  4182. # _____________________________________________________________________________
  4183. #
  4184. # EditBranchSpec
  4185. #
  4186. #
  4187. #
  4188. # Parameters:
  4189. #
  4190. # Output:
  4191. #
  4192. # _____________________________________________________________________________
  4193. sub EditBranchSpec()
  4194. {
  4195. my $sp = $_[0];
  4196. my $pbranch = $_[1];
  4197. my $fullcmd = "";
  4198. $fullcmd = "sd.exe $sp branch $pbranch";
  4199. my $msg = "Edit the branch view to contain only the projects and files to branch.\n";
  4200. sleep(1);
  4201. SDX::RunSDCmd($msg, $fullcmd);
  4202. }
  4203. # _____________________________________________________________________________
  4204. #
  4205. # Resolve
  4206. #
  4207. # called from OtherOp() to resolve integrated files. uses sd -s to get
  4208. # verbose output so we can catch errors
  4209. #
  4210. # Parameters:
  4211. # $labbranch branch name
  4212. # $spproject server:port if codebase type 2, project name if type 1
  4213. # $header user output
  4214. #
  4215. # Output:
  4216. # _____________________________________________________________________________
  4217. sub Resolve
  4218. {
  4219. my $userargs = $_[0];
  4220. my $spproject = $_[1];
  4221. my $header = $_[2];
  4222. my $cmdtype = $_[3];
  4223. my $fullcmd = "";
  4224. $main::V3 and do
  4225. {
  4226. print "\n\n\nuserargs = '$userargs'\n";
  4227. print "spproject = '$spproject'\n";
  4228. };
  4229. #
  4230. # maybe use server:port
  4231. #
  4232. my $sp = SDX::ServerPort($cmdtype, $spproject);
  4233. $fullcmd = "sd.exe $sp -s resolve $userargs 2>&1";
  4234. SDX::RunSDCmd($header, $fullcmd);
  4235. }
  4236. # _____________________________________________________________________________
  4237. #
  4238. # SyncFlush
  4239. #
  4240. # called from OtherOp() to sync files or flush the sync state
  4241. #
  4242. # Parameters:
  4243. # $labbranch branch name
  4244. # $spproject server:port if codebase type 2, project name if type 1
  4245. # $header user output
  4246. #
  4247. # Output:
  4248. # _____________________________________________________________________________
  4249. sub SyncFlush
  4250. {
  4251. my $cmd = $_[0];
  4252. my $userargs = $_[1];
  4253. my $spproject = $_[2];
  4254. my $header = $_[3];
  4255. my $cmdtype = $_[4];
  4256. my $fullcmd = "";
  4257. my $nul = "";
  4258. my $userargs2 = "";
  4259. my $c1 = "";
  4260. my $c2 = "";
  4261. my $err = "Error getting changelists:";
  4262. my $minush = $main::MinusH;
  4263. $userargs2 = $userargs;
  4264. $userargs =~ s/ -(a[mf]|i) //g;
  4265. $main::V2 and do
  4266. {
  4267. print "\n\n\ncmd = '$cmd'\n";
  4268. print "userargs = '$userargs'\n";
  4269. print "userargs2 = '$userargs2'\n";
  4270. print "spproject = '$spproject'\n";
  4271. };
  4272. ###$spproject ne "base" and return;
  4273. ###print "\n\n\tBUGBUG comment this out:\n";
  4274. #
  4275. # maybe use server:port
  4276. #
  4277. my $sp = SDX::ServerPort($cmdtype, $spproject);
  4278. #
  4279. # if -h, user wants to see change lists go by, not files
  4280. # get the most recent change number they have
  4281. #
  4282. # look for depot errors
  4283. #
  4284. $main::MinusH and do
  4285. {
  4286. my @changes = `sd.exe $sp changes -m 1 ...#have 2>&1`;
  4287. grep(/error:/i, @changes) and $minush = SDX::SyncFlushErr($err,\@changes);
  4288. $main::MinusH and do
  4289. {
  4290. #
  4291. # changelist number must be all digits
  4292. # some SD auth errors aren't caught by the check above
  4293. #
  4294. $c1 = (split(/ /, @changes[0]))[1];
  4295. ($c1 =~ /[\D]+/) and $minush = SDX::SyncFlushErr($err,\@changes);
  4296. };
  4297. };
  4298. #
  4299. # do the sync or flush
  4300. #
  4301. $fullcmd = "sd.exe $sp $cmd $userargs 2>&1";
  4302. $header .= "\u$cmd" . "ing...\n";
  4303. SDX::RunSDCmd($header, $fullcmd);
  4304. #
  4305. # get the most recent change number the user just picked up and
  4306. # get the list of changes between this and the previous one
  4307. # only get integration changes if MinusHI
  4308. #
  4309. $main::MinusH and do
  4310. {
  4311. my %changes = ();
  4312. my $revrange = "#have";
  4313. my $hdr = "";
  4314. #
  4315. # if -n we didn't actually sync or flush, so the 2nd change number
  4316. # must be what the user would pick up, not what they currently have
  4317. #
  4318. $userargs =~ / -n / and $revrange = "";
  4319. #
  4320. # get and verify change number
  4321. #
  4322. my @chgs = `sd.exe $sp changes -m 1 ...$revrange 2>&1`;
  4323. grep(/error:/i, @chgs) and $minush = SDX::SyncFlushErr($err,\@chgs);
  4324. #
  4325. # changelist number must be all digits
  4326. # some SD auth errors aren't caught by the check above
  4327. #
  4328. $c2 = (split(/ /, @chgs[0]))[1];
  4329. ($c2 =~ /[\D]+/) and $minush = SDX::SyncFlushErr($err,\@chgs);
  4330. #
  4331. # only show changes if we would or did pick something up
  4332. #
  4333. ($c1 != $c2) and do
  4334. {
  4335. $hdr = "\nListing changes...";
  4336. print "$hdr";
  4337. #
  4338. # use the next change number so we don't show changes we already have
  4339. #
  4340. $c1++;
  4341. #
  4342. # get the change list, first without, then with, integration changes
  4343. # mark previous changes in hash with 1
  4344. # if MinusI
  4345. # mark int changes (not already in hash) with 2
  4346. # sort
  4347. # print int changes tab-indented
  4348. #
  4349. my @changes = `sd.exe $sp changes ...\@$c1,\@$c2 2>&1`;
  4350. grep(/error:/i, @changes) and $minush = SDX::SyncFlushErr($err,\@changes);
  4351. @changes = grep {s/^Change //g} @changes;
  4352. foreach (@changes)
  4353. {
  4354. $changes{$_} = 1;
  4355. print ".";
  4356. }
  4357. $main::MinusI and do
  4358. {
  4359. my @changes = `sd.exe $sp changes -i ...\@$c1,\@$c2 2>&1`;
  4360. grep(/error:/i, @changes) and $minush = SDX::SyncFlushErr($err,\@changes);
  4361. @changes = grep {s/^Change //g} @changes;
  4362. foreach (@changes)
  4363. {
  4364. !$changes{$_} and $changes{$_} = 2;
  4365. }
  4366. print ".";
  4367. };
  4368. sub nn { $b <=> $a; }
  4369. @changes = sort nn keys %changes;
  4370. print ".";
  4371. #
  4372. # print the changes, with integration changes indented
  4373. #
  4374. # maybe log the output
  4375. #
  4376. print "\n";
  4377. $main::Logging and do
  4378. {
  4379. (open LOG, ">>$main::Log" or die("\nCan't append $main::LOG\n"));
  4380. print LOG "$hdr\n";
  4381. };
  4382. foreach $key (@changes)
  4383. {
  4384. my $ch = sprintf "%sChange $key", $changes{$key} == 2 ? " " : "";
  4385. print "$ch";
  4386. $main::Logging and print LOG "$ch";
  4387. #
  4388. # keep stats for OtherOp()
  4389. #
  4390. $ch =~ /^Change / and $main::Changes++;
  4391. $ch =~ / Change / and $main::IntegrationChanges++;
  4392. }
  4393. $main::Logging and close LOG;
  4394. };
  4395. $hdr = sprintf("Enlistment %s in sync through change number %s.\n", ($userargs2 =~ / -n / ? "would be" : "is"), $c2);
  4396. print "$hdr";
  4397. #
  4398. # print the changes, with integration changes indented
  4399. #
  4400. # maybe log the output
  4401. #
  4402. $main::Logging and do
  4403. {
  4404. (open LOG, ">>$main::Log" or die("\nCan't append $main::LOG\n"));
  4405. print LOG "$hdr\n";
  4406. close LOG;
  4407. };
  4408. };
  4409. #
  4410. # see if this is a sync with resolve
  4411. #
  4412. ($cmd eq "sync") and do
  4413. {
  4414. $userargs2 =~ /-am/ and do
  4415. {
  4416. $fullcmd = "sd.exe $sp -s resolve $userargs2 2>&1";
  4417. $header = "\nResolving...\n";
  4418. SDX::RunSDCmd($header, $fullcmd);
  4419. # remove -am for the next call
  4420. $userargs2 =~ s/-am//g;
  4421. $fullcmd = "sd.exe $sp -s resolve -n $userargs2 2>&1";
  4422. $header = "\nLooking for files needing manual resolution...\n";
  4423. SDX::RunSDCmd($header, $fullcmd);
  4424. };
  4425. $userargs2 =~ /-af/ and do
  4426. {
  4427. $fullcmd = "sd.exe $sp -s resolve $userargs2 2>&1";
  4428. $header = "\nResolving...\n";
  4429. SDX::RunSDCmd($header, $fullcmd);
  4430. };
  4431. };
  4432. #
  4433. # maybe restore
  4434. #
  4435. $main::MinusH = $minush;
  4436. }
  4437. # _____________________________________________________________________________
  4438. #
  4439. # SyncFlushErr
  4440. #
  4441. # handle errors
  4442. #
  4443. # Parameters:
  4444. #
  4445. # Output:
  4446. # _____________________________________________________________________________
  4447. sub SyncFlushErr
  4448. {
  4449. my $err = $_[0];
  4450. my ($list) = $_[1];
  4451. #
  4452. # temporarily disable -h
  4453. # print warning
  4454. #
  4455. $main::MinusH = $main::FALSE;
  4456. print "\n$err\n\n@$list\n";
  4457. #
  4458. # count for summary
  4459. #
  4460. $main::DepotErrors++;
  4461. return $main::TRUE;
  4462. }
  4463. # _____________________________________________________________________________
  4464. #
  4465. # Opened
  4466. #
  4467. # called from OtherOp() to get opened files
  4468. #
  4469. # Parameters:
  4470. # $labbranch branch name
  4471. # $spproject server:port if codebase type 2, project name if type 1
  4472. # $header user output
  4473. #
  4474. # Output:
  4475. # _____________________________________________________________________________
  4476. sub Opened
  4477. {
  4478. my $userargs = $_[0];
  4479. my $spproject = $_[1];
  4480. my $header = $_[2];
  4481. my $cmdtype = $_[3];
  4482. my $fullcmd = "";
  4483. my $ch = "";
  4484. $main::V2 and do
  4485. {
  4486. print "\n\n\ncmd = '$cmd'\n";
  4487. print "userargs = '$userargs'\n";
  4488. print "spproject = '$spproject'\n";
  4489. };
  4490. #
  4491. # maybe use server:port
  4492. #
  4493. my $sp = SDX::ServerPort($cmdtype, $spproject);
  4494. #
  4495. # set the basic cmd
  4496. #
  4497. $fullcmd = "sd.exe $sp opened $userargs 2>&1";
  4498. SDX::RunSDCmd($header, $fullcmd);
  4499. }
  4500. # _____________________________________________________________________________
  4501. #
  4502. # Files
  4503. #
  4504. # called from OtherOp() to list files
  4505. #
  4506. # Parameters:
  4507. # $labbranch branch name
  4508. # $spproject server:port if codebase type 2, project name if type 1
  4509. # $header user output
  4510. #
  4511. # Output:
  4512. # _____________________________________________________________________________
  4513. sub Files
  4514. {
  4515. my $userargs = $_[0];
  4516. my $spproject = $_[1];
  4517. my $header = $_[2];
  4518. my $cmdtype = $_[3];
  4519. my $fullcmd = "";
  4520. my $ch = "";
  4521. @main::FileChunks = ();
  4522. $main::DepotFiles = 0;
  4523. $main::V2 and do
  4524. {
  4525. print "\n\n\ncmd = '$cmd'\n";
  4526. print "userargs = '$userargs'\n";
  4527. print "spproject = '$spproject'\n";
  4528. };
  4529. #
  4530. # maybe use server:port
  4531. #
  4532. my $sp = SDX::ServerPort($cmdtype, $spproject);
  4533. #
  4534. # set the basic cmd
  4535. #
  4536. $fullcmd = "sd.exe $sp files $userargs 2>&1";
  4537. #
  4538. # if the user wants a summary file count,
  4539. # chunk the depot into pieces that won't exceed MAXRESULTS
  4540. # save the results in a list
  4541. # use RunSDCmd to print total
  4542. #
  4543. if ($main::MinusA)
  4544. {
  4545. #
  4546. # print header
  4547. #
  4548. SDX::PrintCmd($header, 0);
  4549. (!$main::V2) and do
  4550. {
  4551. my @list = ();
  4552. my @dirs = `sd.exe $sp dirs //*/*/*`;
  4553. foreach (@dirs)
  4554. {
  4555. chop $_;
  4556. my @chunk = `sd.exe files $_/...`;
  4557. push @list, sprintf "%-45s %7s", $_, $#chunk + 1;
  4558. $main::DepotFiles += $#chunk + 1;
  4559. print ".";
  4560. }
  4561. push @main::FileChunks, @list;
  4562. print "\n";
  4563. #
  4564. # run it
  4565. #
  4566. SDX::RunCmd($fullcmd);
  4567. };
  4568. }
  4569. else
  4570. {
  4571. #
  4572. #run it
  4573. #
  4574. SDX::RunSDCmd($header, $fullcmd);
  4575. }
  4576. }
  4577. # _____________________________________________________________________________
  4578. #
  4579. # Status
  4580. #
  4581. # called from OtherOp() to show opened/out of sync files
  4582. #
  4583. # Parameters:
  4584. # $labbranch branch name
  4585. # $spproject server:port if codebase type 2, project name if type 1
  4586. # $header user output
  4587. #
  4588. # Output:
  4589. # _____________________________________________________________________________
  4590. sub Status
  4591. {
  4592. my $userargs = $_[0];
  4593. my $project = $_[1];
  4594. my $header = $_[2];
  4595. my $cmdtype = $_[3];
  4596. my $fullcmd1 = "";
  4597. my $fullcmd2 = "";
  4598. my $arg = "";
  4599. $main::V2 and do
  4600. {
  4601. print "\n\n\nuserargs = '$userargs'\n";
  4602. print "project = '$project'\n";
  4603. };
  4604. #
  4605. # for type 2 depots (N projects/depot) restrict scope to ...
  4606. #
  4607. # for the root project in a type 2 (other than NT), restrict scope to *
  4608. #
  4609. $main::CodeBaseType == 2 and do
  4610. {
  4611. $arg = ($project eq "root" and "\U$main::CodeBase" ne "NT") ? "*" : "...";
  4612. };
  4613. my $fullcmd1 = "sd.exe opened $arg 2>&1";
  4614. my $fullcmd2 = "sd.exe sync -n $arg 2>&1";
  4615. $header .= "Checking for open files...\n";
  4616. my $header2 = "\nChecking for files out of sync...\n";
  4617. if ($main::V2)
  4618. {
  4619. SDX::PrintCmd($header, 0);
  4620. SDX::PrintCmd($fullcmd1, 1);
  4621. SDX::PrintCmd($header2, 0);
  4622. SDX::PrintCmd($fullcmd2, 1);
  4623. }
  4624. else
  4625. {
  4626. SDX::PrintCmd($header, 0);
  4627. SDX::RunCmd($fullcmd1);
  4628. SDX::PrintCmd($header2, 0);
  4629. SDX::RunCmd($fullcmd2);
  4630. }
  4631. }
  4632. # _____________________________________________________________________________
  4633. #
  4634. # Submit
  4635. #
  4636. # called from OtherOp() to handle submit
  4637. #
  4638. # Parameters:
  4639. # $userargs user args
  4640. # $project server:port if codebase type 2, project name if type 1
  4641. # $header user output
  4642. #
  4643. # Output:
  4644. # _____________________________________________________________________________
  4645. sub Submit
  4646. {
  4647. my $userargs = $_[0];
  4648. my $spproject = $_[1];
  4649. my $header = $_[2];
  4650. my $cmdtype = $_[3];
  4651. my $fullcmd = "";
  4652. $main::V2 and do
  4653. {
  4654. print "\n\n\nuserargs = '$userargs'\n";
  4655. print "spproject = '$spproject'\n";
  4656. };
  4657. #
  4658. # maybe use server:port
  4659. #
  4660. my $sp = SDX::ServerPort($cmdtype, $spproject);
  4661. #
  4662. # assume a normal submit where the form gets brought up
  4663. #
  4664. $fullcmd = "sd.exe $sp submit $userargs 2>&1";
  4665. #
  4666. # special case if the user put the comment on the cmd line
  4667. #
  4668. ($main::SubmitComment) and do
  4669. {
  4670. #
  4671. # dump the default changelist
  4672. #
  4673. @main::InputForm = `sd.exe $sp change -o 2>&1`;
  4674. #
  4675. # if it contains a file list, use it as the submit form,
  4676. # inserting the comment
  4677. #
  4678. # add -i to the sd cmd before passing it on
  4679. #
  4680. if (grep(/Files:$/, @main::InputForm))
  4681. {
  4682. foreach $_ (@main::InputForm) { $_ =~ s/<enter description here>/$main::SubmitComment/g; }
  4683. $main::V2 and print "submit form:\n\n'@main::InputForm'\n";
  4684. $fullcmd = "sd.exe $sp submit -i 2>&1";
  4685. }
  4686. };
  4687. SDX::RunSDCmd($header, $fullcmd);
  4688. }
  4689. # _____________________________________________________________________________
  4690. #
  4691. # InitForEDR
  4692. #
  4693. # Do some common initialization for enlist, repair and defect
  4694. #
  4695. # Parameters:
  4696. # Command Line Arguments
  4697. #
  4698. # Output:
  4699. #
  4700. # _____________________________________________________________________________
  4701. sub InitForEDR
  4702. {
  4703. my $enlisting = ($_[0] eq "enlist");
  4704. my $defecting = ($_[0] eq "defect");
  4705. my $repairing = ($_[0] eq "repair");
  4706. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in InitForEDR().\n");
  4707. #
  4708. # init global vars and flags
  4709. #
  4710. $main::EnlistingMainBranch = $main::FALSE;
  4711. $main::EnlistingGroupBranch = $main::FALSE;
  4712. $main::EnlistingPrivateBranch = $main::FALSE;
  4713. $main::ClientView = "$main::SDXRoot\\clientview";
  4714. $main::CBMProjectField = 0; # change these if you change
  4715. $main::CBMGroupField = 1; # the ordering of fields in
  4716. $main::CBMServerPortField = 2; # file PROJECTS.<CODEBASE>
  4717. $main::CBMDepotNameField = 3;
  4718. $main::CBMProjectRootField = 4;
  4719. $main::MasterBranch = "";
  4720. @main::GroupBranches = ();
  4721. @main::EnlistProjects = ();
  4722. @main::EnlistGroups = ();
  4723. @main::EnlistDepots = ();
  4724. @main::DefectDepots = ();
  4725. @main::DefectProjects = ();
  4726. #
  4727. # if we're running from a razzle window, error out
  4728. #
  4729. $main::SDUser =~ /(x86|amd64|ia64)(fre|chk)/ and do
  4730. {
  4731. print "\nCan't run 'sdx enlist' from a build window -- can't use '$ENV{USERNAME}' as \%SDUSER\%.\n";
  4732. print "\nSet \%SDUSER\% to your login name or run 'sdx enlist' from a clean command\n";
  4733. print "window.\n";
  4734. die("\n");
  4735. };
  4736. #
  4737. # make sure we have PROJECTS.<codebase>
  4738. #
  4739. !SDX::VerifyCBMap($main::CodeBase) and do
  4740. {
  4741. print "\n\nCan't find codebase map $main::CodeBaseMap.\n";
  4742. print "\nRun 'sdx repair $main::CodeBase $main::Branch' from the SDX share from which you originally\n";
  4743. print "enlisted.\n";
  4744. die("\n");
  4745. };
  4746. #
  4747. # if not defecting, make the enlistment root
  4748. #
  4749. !$defecting and do
  4750. {
  4751. system "md $main::SDXRoot >nul 2>&1";
  4752. -e $main::SDXRoot or die("\nCan't create root dir $main::SDXRoot.\n");
  4753. };
  4754. #
  4755. # read the codebase map
  4756. # get MainBranch and GroupBranches list
  4757. # get master list of project.group.server:port.depot.projroot mappings
  4758. #
  4759. SDX::ReadCodeBaseMap();
  4760. #
  4761. # create the lists of all projects, groups and depots, removing any duplicates
  4762. #
  4763. SDX::MakePGDLists("");
  4764. #
  4765. # make sure we have a valid Tools project
  4766. #
  4767. $main::ToolsProject and do
  4768. {
  4769. my $found = $main::FALSE;
  4770. foreach $proj (@main::AllProjects)
  4771. {
  4772. (@$proj[0] eq $main::ToolsProject) and $found = $main::TRUE and last;
  4773. }
  4774. !$found and die("\nUnknown tools project \U'$main::ToolsProject'. C\Lheck the codebase map.\n");
  4775. };
  4776. }
  4777. # _____________________________________________________________________________
  4778. #
  4779. # VerifyAccess
  4780. #
  4781. # verify access to the relevant servers, dies if unable to access
  4782. #
  4783. # Parameters:
  4784. # none
  4785. #
  4786. # Output:
  4787. # prints status information to the screen while running and an error message
  4788. # for fatal errors
  4789. # _____________________________________________________________________________
  4790. sub VerifyAccess {
  4791. print "\nVerifying access to depots.";
  4792. for $depot (@main::VerifyDepots)
  4793. {
  4794. print ".";
  4795. my $serverport = @$depot[0];
  4796. my @err = `sd.exe -p $serverport client -o 2>&1`;
  4797. grep(/ failed/, @err) and die("\n\n@err\n");
  4798. SDX::AccessDenied(\@err, $serverport) and die("\n");
  4799. }
  4800. print "\nok\n";
  4801. }
  4802. # _____________________________________________________________________________
  4803. #
  4804. # RemoveFromView
  4805. #
  4806. # Parameters:
  4807. #
  4808. # Output:
  4809. # returns 1 if a reduced client view exists, 0 if the view ends up empty or client
  4810. # doesn't exist in this depot
  4811. # _____________________________________________________________________________
  4812. sub RemoveFromView
  4813. {
  4814. my $depot = $_[0];
  4815. my $serverport = @$depot[0];
  4816. my $depotname = @$depot[1];
  4817. unlink $main::ClientView;
  4818. #
  4819. # write the default view lines for this depot and project(s)
  4820. #
  4821. SDX::WriteDefaultView($serverport, $depotname);
  4822. if (SDX::ClientExists($serverport, $main::SDClient))
  4823. {
  4824. print "Editing client view.";
  4825. #
  4826. # read the existing client view into @main::ExistingView
  4827. # and write the existing header to $main::ClientView
  4828. #
  4829. SDX::GetClientView("defect", $serverport, $main::SDClient);
  4830. #
  4831. # use the existing view lines as keys to a hash and
  4832. # mark each entry in ascending order
  4833. #
  4834. # using the default view lines as keys to the same
  4835. # hash, mark each entry found with 0 to indicate removed
  4836. #
  4837. # write the remaining hash lines back into the list
  4838. # and sort it back to its original order, which is how
  4839. # the user had it
  4840. #
  4841. my @tmpview = ();
  4842. my @tmpview2 = ();
  4843. my @finalview = ();
  4844. my @finalview2 = ();
  4845. my $linenum = 1;
  4846. # must be global for sort to work
  4847. %existingview = ();
  4848. %existingview2 = ();
  4849. #
  4850. # lowercase the line, so we don't keep
  4851. # duplicates that only differ by case
  4852. #
  4853. foreach $line (@main::ExistingView)
  4854. {
  4855. $existingview{"\L$line"} = $linenum++;
  4856. }
  4857. $main::V3 and do
  4858. {
  4859. print "\nhash:\n";
  4860. while (($k,$v) = each %existingview)
  4861. {
  4862. printf "'%-50s'\t'%s'\n", $k, $v;
  4863. }
  4864. };
  4865. foreach $line (@main::DefaultView)
  4866. {
  4867. #
  4868. # extract the LHS of the default line as line2
  4869. # add '-' to find negation mappings
  4870. #
  4871. @fields = split(/\//,$line);
  4872. my $line2 = "";
  4873. for $x (0..4)
  4874. {
  4875. $line2 .= @fields[$x] . "/";
  4876. }
  4877. chop $line2;
  4878. my $line3 = $line2;
  4879. $line3 =~ s/\/\//-\/\//;
  4880. #
  4881. # mark any lines in the existing view that match
  4882. # the default line exactly
  4883. #
  4884. if ($existingview{"\L$line"})
  4885. {
  4886. $existingview{"\L$line"} = 0;
  4887. print ".";
  4888. }
  4889. #
  4890. # mark any lines which have the same LHS as the
  4891. # default line, including those that begin with '-'
  4892. #
  4893. while (($k,$v) = each %existingview)
  4894. {
  4895. if (($k =~ /^$line2/) || ($k =~ /^$line3/))
  4896. {
  4897. # print "\nmatch: '$k'\n";
  4898. $existingview{$k} = 0;
  4899. }
  4900. }
  4901. }
  4902. $main::V3 and print "\n\n\n\nhash, edited:\n";
  4903. while (($k,$v) = each %existingview)
  4904. {
  4905. $v and push @tmpview, $k;
  4906. $main::V3 and printf "'%-50s'\t'%s'\n", $k, $v;
  4907. }
  4908. #
  4909. # sort ascending on the numeric value of each key
  4910. #
  4911. sub ascending { my $rc = ($existingview{$a} <=> $existingview{$b}); }
  4912. @finalview = sort ascending @tmpview;
  4913. $main::V2 and print "\nfinal view:\n@finalview\n";
  4914. #
  4915. # if we still have a view and it still has valid project mappings,
  4916. # finish writing the client view by appending the newly reduced view spec
  4917. # else return
  4918. #
  4919. ### if (@finalview && !SDX::PrivateView($depot, \@finalview))
  4920. if (@finalview)
  4921. {
  4922. open(CLIENTVIEW, ">>$main::ClientView") or die("\nCan't open $main::ClientView for writing.\n");
  4923. for $viewline (@finalview)
  4924. {
  4925. printf CLIENTVIEW $viewline;
  4926. }
  4927. close(CLIENTVIEW);
  4928. return 1;
  4929. }
  4930. else
  4931. {
  4932. return 0;
  4933. }
  4934. }
  4935. else
  4936. {
  4937. return 0;
  4938. }
  4939. }
  4940. # _____________________________________________________________________________
  4941. #
  4942. # PrivateView
  4943. #
  4944. # Determines if the list of view lines passed in contains any default project
  4945. # mappings. A view still containing such mappings means we have more than just
  4946. # the user's view customizations and can't throw the view away yet.
  4947. #
  4948. # Parameters:
  4949. # none
  4950. #
  4951. # Output:
  4952. # returns 1 if view has only private mappings and no default project lines in it
  4953. # 0 otherwise
  4954. # _____________________________________________________________________________
  4955. sub PrivateView
  4956. {
  4957. my $depot = $_[0];
  4958. my @view = $_[1];
  4959. my $serverport = @$depot[0];
  4960. #
  4961. # load the remaining view lines into a hash and mark each,
  4962. # ignoring lines beginning with '-'
  4963. #
  4964. #
  4965. # if hash is empty, return 1
  4966. #
  4967. #
  4968. # else get the full list of project view lines for all projects in this depot
  4969. #
  4970. #
  4971. # for each view line, return as soon as we get a hit
  4972. # if (hash{$viewline}) return 0
  4973. #
  4974. return 1;
  4975. }
  4976. # _____________________________________________________________________________
  4977. #
  4978. # ReadCodeBaseMap
  4979. #
  4980. # reads master branch, group branch list, and project.group.server:port.depot.projroot
  4981. # mappings into lists to manipulate later.
  4982. #
  4983. # Parameters:
  4984. #
  4985. # Output:
  4986. # sets $main::MasterBranch
  4987. # populates $main::GroupBranches list
  4988. # populates $main::AllMappings list
  4989. # _____________________________________________________________________________
  4990. sub ReadCodeBaseMap
  4991. {
  4992. open(CODEBASEMAP, $main::CodeBaseMap) or die("\nCan't open code base map $main::CodeBaseMap.\n");
  4993. while ($cbmline = <CODEBASEMAP>)
  4994. {
  4995. #
  4996. # throw away comments
  4997. #
  4998. $cbmline =~ /^#/ and next;
  4999. chop $cbmline;
  5000. #
  5001. # make sure the codebase we think we are matches SDX
  5002. #
  5003. if ($cbmline =~ /^CODEBASE[\t\s]*=/)
  5004. {
  5005. @fields = split(/[\t\s]*=[\t\s]*/, $cbmline);
  5006. $actualcb = @fields[1];
  5007. $actualcb =~ s/[\t\s]*//g;
  5008. $main::CodeBase =~ /$actualcb/i or die("\nError: Codebase name '$actualcb' in $main::CodeBaseMap doesn't match '$main::CodeBase'.\n");
  5009. }
  5010. #
  5011. # get the codebase type
  5012. #
  5013. if ($cbmline =~ /^CODEBASETYPE/)
  5014. {
  5015. $main::CodeBaseType = (split(/[\t\s]*=[\t\s]*/, $cbmline))[1];
  5016. next;
  5017. }
  5018. #
  5019. # get the master branch
  5020. #
  5021. if ($cbmline =~ /^MASTERBRANCH/)
  5022. {
  5023. @fields = split(/[\t\s]*=[\t\s]*/, $cbmline);
  5024. $main::MasterBranch = @fields[1];
  5025. $main::MasterBranch =~ s/[\t\s]*//g;
  5026. }
  5027. #
  5028. # get the group branches
  5029. #
  5030. if ($cbmline =~ /^GROUPBRANCHES/)
  5031. {
  5032. $cbmline =~ s/^GROUPBRANCHES[\t\s]*=[\t\s]*//g;
  5033. @main::GroupBranches = split(/[\t\s]+/, $cbmline);
  5034. }
  5035. #
  5036. # figure out whether we should give the user SD tools after
  5037. # enlisting or not
  5038. #
  5039. if ($cbmline =~ /^TOOLS/)
  5040. {
  5041. $cbmline =~ s/^TOOLS[\t\s]*=[\t\s]*//g;
  5042. @fields = split(/\\/, $cbmline);
  5043. # first token is always the project
  5044. $main::ToolsProject = "\L@fields[0]";
  5045. #
  5046. # if we have a project, get the relative and full paths to it
  5047. #
  5048. $main::ToolsProject and do
  5049. {
  5050. shift @fields;
  5051. foreach $p (@fields)
  5052. {
  5053. $main::ToolsPath .= "\L$p" . "\\";
  5054. }
  5055. $main::ToolsPath and chop $main::ToolsPath;
  5056. #
  5057. # if at the root, the full path doesn't include the project name
  5058. #
  5059. #
  5060. # only include a "\" below if SDXROOT doesn't end in one already
  5061. #
  5062. my $dblslash = ($main::SDXRoot =~ /\\$/ ? "" : "\\");
  5063. if ($main::ToolsProject eq "root")
  5064. {
  5065. #
  5066. # if the CBM lists "root" for the tools and we have no path, error out
  5067. #
  5068. !$main::ToolsPath and die("\nTools project is ROOT but no path was specified in \U$main::CodeBaseMap.\n");
  5069. $main::ToolsProjectPath = $main::SDXRoot . $dblslash . $main::ToolsPath;
  5070. $main::ToolsInRoot = $main::TRUE;
  5071. }
  5072. else
  5073. {
  5074. $main::ToolsProjectPath = $main::SDXRoot . $dblslash . $main::ToolsProject;
  5075. $main::ToolsPath and $main::ToolsProjectPath .= "\\" . $main::ToolsPath;
  5076. }
  5077. };
  5078. }
  5079. #
  5080. # get any other dirs to be sync'd on the user's behalf
  5081. #
  5082. if ($cbmline =~ /^OTHERDIRS/)
  5083. {
  5084. $cbmline =~ s/^OTHERDIRS[\t\s]*=[\t\s]*//g;
  5085. @main::OtherDirs = split(/[\t\s]+/,$cbmline);
  5086. }
  5087. #
  5088. # get any required projects
  5089. #
  5090. if ($cbmline =~ /^DEFAULTPROJECTS/)
  5091. {
  5092. $cbmline =~ s/^DEFAULTPROJECTS[\t\s]*=[\t\s]*//g;
  5093. @main::DefaultProjects = split(/[\t\s]+/,$cbmline);
  5094. }
  5095. #
  5096. # get any projects that need platform-specific subdirs trimmed
  5097. # in the view
  5098. #
  5099. if ($cbmline =~ /^PLATFORMPROJECTS/)
  5100. {
  5101. $cbmline =~ s/^PLATFORMPROJECTS[\t\s]*=[\t\s]*//g;
  5102. @main::PlatformProjects = split(/[\t\s]+/,$cbmline);
  5103. }
  5104. #
  5105. # see if we need to restrict the Root mapping
  5106. #
  5107. if ($cbmline =~ /^RESTRICTROOT/)
  5108. {
  5109. $cbmline =~ s/^RESTRICTROOT[\t\s]*=[\t\s]*//g;
  5110. $restrict = $cbmline;
  5111. $restrict =~ s/[\t\s]*//g;
  5112. if ($restrict eq "1" || "\U$restrict" eq "YES")
  5113. {
  5114. $main::RestrictRoot = $main::TRUE;
  5115. }
  5116. }
  5117. #
  5118. # if not one of the above, the line is a project-group-server:port-depot-projroot mapping
  5119. #
  5120. # lowercase the whole line, split it, then push it onto a list
  5121. #
  5122. if ($cbmline =~ /[a-zA-Z0-9]+:[0-9]+/)
  5123. {
  5124. $main::nMappings++;
  5125. @fields = split(/[\t\s]+/, "\L$cbmline");
  5126. push @main::AllMappings, [@fields];
  5127. }
  5128. }
  5129. close(CODEBASEMAP);
  5130. $main::V3 and do
  5131. {
  5132. print "\n";
  5133. printf "readcbm: \# mappings = %s\n", $main::nMappings;
  5134. printf "readcbm: codebase = '%s'\n", $main::CodeBase;
  5135. printf "readcbm: codebasetype = '%s'\n", $main::CodeBaseType;
  5136. printf "readcbm: masterbranch ='%s'\n", $main::MasterBranch;
  5137. if ($main::ToolsProject)
  5138. {
  5139. printf "readcbm: toolsproject='%s'\n", $main::ToolsProject;
  5140. printf "readcbm: toolspath='%s'\n", $main::ToolsPath;
  5141. printf "readcbm: toolsprojectpath='%s'\n", $main::ToolsProjectPath;
  5142. }
  5143. if (@main::OtherDirs)
  5144. {
  5145. foreach $d (@main::OtherDirs)
  5146. {
  5147. printf "readcbm: otherdir='%s'\n", $d;
  5148. }
  5149. }
  5150. if (@main::DefaultProjects)
  5151. {
  5152. foreach $d (@main::DefaultProjects)
  5153. {
  5154. printf "readcbm: defproj='%s'\n", $d;
  5155. }
  5156. }
  5157. if (@main::PlatformProjects)
  5158. {
  5159. foreach $d (@main::PlatformProjects)
  5160. {
  5161. printf "readcbm: platproj='%s'\n", $d;
  5162. }
  5163. }
  5164. foreach $b (@main::GroupBranches)
  5165. {
  5166. printf "readcbm: grbr='%s'\n", $b;
  5167. }
  5168. print "\n";
  5169. for $x (0..$main::nMappings-1)
  5170. {
  5171. for $y (0..4)
  5172. {
  5173. printf "readcbm: AllMappings[%s][%s] = %s\n", $x, $y, $main::AllMappings[$x][$y];
  5174. }
  5175. print "\n";
  5176. }
  5177. };
  5178. }
  5179. # _____________________________________________________________________________
  5180. #
  5181. # MakePGDLists
  5182. #
  5183. # Munges $main::AllMappings to create lists of projects, groups and servers.
  5184. #
  5185. # Parameters:
  5186. #
  5187. # Output:
  5188. # populates @main::AllProjects as 2D array with full mappings for all unique project names
  5189. # populates @main::AllGroups with list of all unique dev groups
  5190. # populates @main::AllDepots with list of all unique SD servers for this codebase
  5191. # _____________________________________________________________________________
  5192. sub MakePGDLists
  5193. {
  5194. #
  5195. # for each project, group, depot
  5196. # unless already seen, add to hash and push to corresponding array
  5197. #
  5198. $p = 0;
  5199. $g = 0;
  5200. $d = 0;
  5201. %seenproj = ();
  5202. %projhash = ();
  5203. %seengroup = ();
  5204. %seenserverport = ();
  5205. @fulldepotdesc = ();
  5206. for $x (0..$main::nMappings-1)
  5207. {
  5208. $proj = $main::AllMappings[$x][$main::CBMProjectField];
  5209. $group = $main::AllMappings[$x][$main::CBMGroupField];
  5210. $serverport = $main::AllMappings[$x][$main::CBMServerPortField];
  5211. $depotname = $main::AllMappings[$x][$main::CBMDepotNameField];
  5212. unless ($seenproj{$proj})
  5213. {
  5214. $p++;
  5215. $seenproj{$proj} = 1;
  5216. push @main::AllProjects, [@{$main::AllMappings[$x]}];
  5217. #
  5218. # place in hash -- use this later
  5219. #
  5220. $projhash{$proj} = [@{$main::AllMappings[$x]}];
  5221. }
  5222. unless ($seengroup{$group})
  5223. {
  5224. $g++;
  5225. $seengroup{$group} = 1;
  5226. push @main::AllGroups, $group;
  5227. }
  5228. unless ($seenserverport{$serverport})
  5229. {
  5230. $d++;
  5231. $seenserverport{$serverport} = 1;
  5232. @fulldepotdesc = ("$serverport","$depotname");
  5233. push @main::AllDepots, [@fulldepotdesc];
  5234. }
  5235. }
  5236. #
  5237. # set up a hash of project types
  5238. #
  5239. # project is type 1 (1 project per depot) if Group field
  5240. # in codebase map is "ntdev"
  5241. #
  5242. # project is type 2 (N projects per depot) otherwise
  5243. #
  5244. %main::ProjectType = ();
  5245. foreach $project (@main::AllProjects)
  5246. {
  5247. $main::ProjectType{@$project[$main::CBMProjectField]} = ("\L@$project[$main::CBMGroupField]" eq "ntdev") ? 1 : 2;
  5248. }
  5249. #
  5250. # figure out depot types
  5251. #
  5252. # a depot is type 1 if its server:port appears in the AllProjects list only once and
  5253. # its Group is "ntdev"
  5254. # else type 2
  5255. #
  5256. for $depot (@main::AllDepots)
  5257. {
  5258. $serverport = @$depot[0];
  5259. my $foundproj = "";
  5260. my $foundgroup = "";
  5261. my $count = 0;
  5262. foreach $project (@main::AllProjects)
  5263. {
  5264. $p = @$project[0];
  5265. $group = @$project[1];
  5266. $sp = @$project[2];
  5267. ($serverport eq $sp) and do
  5268. {
  5269. $count++;
  5270. $foundproj = $p;
  5271. $foundgroup = $group;
  5272. $count > 1 and last;
  5273. }
  5274. }
  5275. if ($count == 1)
  5276. {
  5277. @{$main::DepotType{$serverport}}[0] = ($foundgroup eq "ntdev") ? 1 : 2;
  5278. @{$main::DepotType{$serverport}}[1] = ($foundgroup eq "ntdev") ? $foundproj : "";
  5279. }
  5280. if ($count > 1)
  5281. {
  5282. @{$main::DepotType{$serverport}}[0] = 2;
  5283. @{$main::DepotType{$serverport}}[1] = "";
  5284. }
  5285. }
  5286. $main::V3 and do
  5287. {
  5288. # printf "\n\# of mappings = %s\n", $#main::AllMappings + 1;
  5289. # foreach $line (@main::AllMappings)
  5290. # {
  5291. # print "pgdlists: AllMappings[] = @$line\n";
  5292. # }
  5293. print "\n";
  5294. printf "\n\# of projects = %s\n", $#main::AllProjects + 1;
  5295. foreach $project (@main::AllProjects)
  5296. {
  5297. print "pgdlists: AllProjects[] = @$project\n";
  5298. }
  5299. print "\n";
  5300. # print "pgdlists: \%projhash:\n";
  5301. # while (($k,$v) = each %projhash)
  5302. # {
  5303. # printf "%20s\t", $k;
  5304. # print "@$v\n";
  5305. # }
  5306. print "pgdlists: \%ProjectType:\n";
  5307. while (($k,$v) = each %main::ProjectType)
  5308. {
  5309. printf "%20s\t", $k;
  5310. print "$v\n";
  5311. }
  5312. printf "\n\# of groups = %s\n", $#main::AllGroups + 1;
  5313. for $group (@main::AllGroups)
  5314. {
  5315. printf "pgdlists: AllGroups[] = $group\n";
  5316. }
  5317. printf "\n\# of depots = %s\n", $#main::AllDepots + 1;
  5318. for $depot (@main::AllDepots)
  5319. {
  5320. printf "pgdlists: AllDepots[] = @$depot\n";
  5321. }
  5322. print "\npgdlists: \%DepotType:\n";
  5323. while (($k,$v) = each %main::DepotType)
  5324. {
  5325. (@$v[0] == 1) and do
  5326. {
  5327. printf " %-50s\t", $k;
  5328. print "@$v[0], @$v[1]\n";
  5329. };
  5330. }
  5331. while (($k,$v) = each %main::DepotType)
  5332. {
  5333. (@$v[0] == 2) and do
  5334. {
  5335. printf " %-50s\t", $k;
  5336. print "@$v[0], @$v[1]\n";
  5337. };
  5338. }
  5339. };
  5340. }
  5341. # _____________________________________________________________________________
  5342. #
  5343. # MakeTargetLists
  5344. #
  5345. # Munges @main::AllProjects and @main::AllDepots to create @main::EnlistProjects and
  5346. # @main::EnlistDepots, the lists of just those projects and depots we'll actually
  5347. # enlist in.
  5348. #
  5349. # Parameters:
  5350. #
  5351. # Output:
  5352. # populates @main::EnlistProjects with projects to enlist
  5353. # populates @main::EnlistDepots with depots to enlist
  5354. # _____________________________________________________________________________
  5355. sub MakeTargetLists
  5356. {
  5357. my $enlisting = ($_[0] eq "enlist");
  5358. my $defecting = ($_[0] eq "defect");
  5359. my $repairing = ($_[0] eq "repair");
  5360. my @depots = ();
  5361. my @projects = ();
  5362. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in MakeTargetLists().\n");
  5363. #
  5364. # if EnlistAll or DefectAll, the projects list depends on the codebase map or SD.MAP
  5365. # else the projects list consists of the rows for each in SomeProjects
  5366. #
  5367. if ($main::EnlistAll || $main::DefectAll)
  5368. {
  5369. #
  5370. # enlist in everything
  5371. #
  5372. $main::EnlistAll and @projects = @main::AllProjects;
  5373. #
  5374. # defect from everything in SD.MAP
  5375. #
  5376. $main::DefectAll and do
  5377. {
  5378. #
  5379. # for each project in @main::SDMapProjects, get the full
  5380. # project:group:depot:projroot mapping associated with it
  5381. # from the AllProjects list
  5382. #
  5383. foreach $project (@main::SDMapProjects)
  5384. {
  5385. my $found = $main::FALSE;
  5386. my $proj = @$project[0];
  5387. foreach $project2 (@main::AllProjects)
  5388. {
  5389. my $proj2 = @$project2[$main::CBMProjectField];
  5390. if ("\l$proj" eq "\l$proj2")
  5391. {
  5392. push @projects, [@{$project2}];
  5393. $found = $main::TRUE;
  5394. last;
  5395. }
  5396. }
  5397. !$found and print "Unknown project $proj in SD.MAP.\n";
  5398. }
  5399. };
  5400. }
  5401. else
  5402. {
  5403. print "\n";
  5404. #
  5405. # if enlisting
  5406. # if EnlistAsOther
  5407. # populate @main::SomeProjects with the list of projects
  5408. # the other client is enlisted in
  5409. #
  5410. if ($enlisting)
  5411. {
  5412. if ($main::EnlistAsOther)
  5413. {
  5414. my $found = $main::FALSE;
  5415. my %projects = ();
  5416. #
  5417. # be verbose if there are more than 3 depots to search
  5418. #
  5419. my $verbose = ($#main::AllDepots > 2);
  5420. $verbose and print "Getting client information for \U$main::OtherClient.";
  5421. #
  5422. # if OtherClient exists in each depot, get the view lines
  5423. # and extract the project names. put them in a hash for
  5424. # uniqueness
  5425. #
  5426. foreach $depot (@main::AllDepots)
  5427. {
  5428. $verbose and print ".";
  5429. my $serverport = @$depot[0];
  5430. if (SDX::ClientExists($serverport, $main::OtherClient))
  5431. {
  5432. $found = $main::TRUE;
  5433. SDX::GetClientView("repair", $serverport, $main::OtherClient);
  5434. # print "\n$main::OtherClient view in $serverport = \n'@main::ExistingView'\n";
  5435. my @fields = ();
  5436. foreach $line (@main::ExistingView)
  5437. {
  5438. #
  5439. # throw away " -//" negation lines
  5440. # and //depot/private lines
  5441. #
  5442. $line =~ /^[\t\s]+-/ and next;
  5443. $line =~ /^[\t\s]+\/\/depot\/private/ and next;
  5444. @fields = split(/\//,$line);
  5445. $projects{$fields[4]} = 1;
  5446. }
  5447. }
  5448. }
  5449. while (($k,$v) = each %projects)
  5450. {
  5451. push @main::SomeProjects, $k;
  5452. }
  5453. $main::V2 and print "\n\n$main::OtherClient projects = @main::SomeProjects\n";
  5454. print "\n";
  5455. !$found and do
  5456. {
  5457. printf "\nClient %s was not found in any of the %s depots. Please choose\n", "\U$main::OtherClient", "\U$main::CodeBase";
  5458. print "another client as a template.\n";
  5459. die("\n");
  5460. };
  5461. }
  5462. #
  5463. # for each proj in the DefaultProjects list, add it to
  5464. # the SomeProjects list if it doesn't already exist there
  5465. # and (for all but new enlistments) it's not already enlisted
  5466. #
  5467. # this should use a hash
  5468. #
  5469. foreach $defproj (@main::DefaultProjects)
  5470. {
  5471. $found = $main::FALSE;
  5472. # print "defproj = '\l$defproj'\n";
  5473. foreach $someproj (@main::SomeProjects)
  5474. {
  5475. # print "\tsomeproj = \l$someproj\n";
  5476. ("\l$defproj" eq "\l$someproj") and do
  5477. {
  5478. $found = $main::TRUE;
  5479. last;
  5480. }
  5481. }
  5482. $main::IncrEnlist and do
  5483. {
  5484. foreach $p (@main::SDMapProjects)
  5485. {
  5486. # print "\t\tp = '\l@$p[0]'\n";
  5487. ("\l$defproj" eq "\l@$p[0]") and do
  5488. {
  5489. $found = $main::TRUE;
  5490. last;
  5491. }
  5492. }
  5493. };
  5494. !$found and push @main::SomeProjects, $defproj;
  5495. }
  5496. }
  5497. #
  5498. # if defecting, don't let the user remove any Default Projects
  5499. #
  5500. if ($defecting)
  5501. {
  5502. #
  5503. # load SomeProjects into a hash
  5504. #
  5505. # for each default project, mark it as unwanted (0)
  5506. #
  5507. # write the wanted (1) hash entries back into a list
  5508. #
  5509. @tmpproj = ();
  5510. %someproj = ();
  5511. foreach $sp (@main::SomeProjects)
  5512. {
  5513. $someproj{$sp} = 1;
  5514. }
  5515. $main::V3 and do
  5516. {
  5517. while (($k,$v) = each %someproj)
  5518. {
  5519. printf "%20s\t%s\n", $k, $v;
  5520. }
  5521. };
  5522. $found = $main::FALSE;
  5523. foreach $dp (@main::DefaultProjects)
  5524. {
  5525. if ($someproj{$dp} == 1)
  5526. {
  5527. $found = $main::TRUE;
  5528. $someproj{$dp} = 0;
  5529. printf "Ignoring default project %s.\n", "\U$dp";
  5530. }
  5531. }
  5532. $found and print "\nUse -a to defect from required projects.\n\n";
  5533. while (($k,$v) = each %someproj)
  5534. {
  5535. $v and push @tmpproj, $k;
  5536. $main::V3 and printf "%20s\t%s\n", $k, $v;
  5537. }
  5538. @main::SomeProjects = sort @tmpproj;
  5539. }
  5540. #
  5541. # at this point @main::SomeProjects has been populated
  5542. #
  5543. # for each proj named in @main::SomeProjects, get the full
  5544. # project:group:depot:projroot mapping associated with it
  5545. # from the AllProjects list
  5546. #
  5547. foreach $project (@main::SomeProjects)
  5548. {
  5549. $found = $main::FALSE;
  5550. foreach $project2 (@main::AllProjects)
  5551. {
  5552. $proj = @$project2[$main::CBMProjectField];
  5553. if ("\L$project" eq "\L$proj")
  5554. {
  5555. push @projects, [@{$project2}];
  5556. $found = $main::TRUE;
  5557. last;
  5558. }
  5559. }
  5560. !$found and print "Unknown project $project.\n";
  5561. }
  5562. }
  5563. #
  5564. # create a list of just those depots we will enlist in
  5565. #
  5566. # for each depot in the AllDepots list, if it exists in the
  5567. # EnlistProjects list, add it to the EnlistDepots list
  5568. #
  5569. foreach $depot (@main::AllDepots)
  5570. {
  5571. # printf "%s\n", @$depot[0];
  5572. foreach $project (@projects)
  5573. {
  5574. $serverport = @$project[$main::CBMServerPortField];
  5575. # printf "\t%s\n", $serverport;
  5576. if (@$depot[0] eq $serverport)
  5577. {
  5578. # printf "\t\t%s\n", $serverport;
  5579. push @depots, [@{$depot}];
  5580. last;
  5581. }
  5582. }
  5583. }
  5584. #
  5585. # assign the depot/project lists accordingly
  5586. #
  5587. $enlisting and do
  5588. {
  5589. @main::EnlistDepots = @depots;
  5590. @main::EnlistProjects = @projects;
  5591. };
  5592. $defecting and do
  5593. {
  5594. @main::DefectDepots = @depots;
  5595. @main::DefectProjects = @projects;
  5596. };
  5597. #
  5598. # remember relevant depots to check for access
  5599. #
  5600. @main::VerifyDepots = @depots;
  5601. @main::VerifyProjects = @projects;
  5602. $main::V3 and do
  5603. {
  5604. if ($enlisting)
  5605. {
  5606. print "\n";
  5607. foreach $project (@main::EnlistProjects)
  5608. {
  5609. print "mtl: EnlistProjects[] = @$project\n";
  5610. }
  5611. print "\n";
  5612. foreach $depot (@main::EnlistDepots)
  5613. {
  5614. print "mtl: EnlistDepots = @$depot\n";
  5615. }
  5616. }
  5617. if ($defecting)
  5618. {
  5619. print "\n";
  5620. foreach $project (@main::DefectProjects)
  5621. {
  5622. print "mtl: DefectProjects[] = @$project\n";
  5623. }
  5624. print "\n";
  5625. foreach $depot (@main::DefectDepots)
  5626. {
  5627. print "mtl: DefectDepots = @$depot\n";
  5628. }
  5629. }
  5630. };
  5631. }
  5632. # _____________________________________________________________________________
  5633. #
  5634. # SortDepots
  5635. #
  5636. # Parameters:
  5637. # @unsorted -- simple array of depot server:ports
  5638. #
  5639. # Output:
  5640. # @sorted -- simple array, sorted first by type (1 or 2) then alpha for
  5641. # the type 1's
  5642. # _____________________________________________________________________________
  5643. sub SortDepots
  5644. {
  5645. my ($unsorted) = $_[0];
  5646. my @sorted = ();
  5647. my @list = ();
  5648. #
  5649. # for each type 1 depot, put its project name in a list
  5650. #
  5651. # sort the list
  5652. #
  5653. $main::V3 and print "\nunsorted depots:\n";
  5654. foreach $sp (@$unsorted)
  5655. {
  5656. (@{$main::DepotType{$sp}}[0] == 1) and push @list, @{$main::DepotType{$sp}}[1];
  5657. $main::V3 and printf " %20s %s\n", @{$main::DepotType{$sp}}[1], $sp;
  5658. }
  5659. @list = sort @list;
  5660. foreach $p (@list)
  5661. {
  5662. foreach $sp (@$unsorted)
  5663. {
  5664. (@{$main::DepotType{$sp}}[1] eq $p) and push @sorted, $sp;
  5665. }
  5666. }
  5667. #
  5668. # add the rest of the (type 2) depots to the list w/o sorting
  5669. #
  5670. foreach $sp (@$unsorted)
  5671. {
  5672. (@{$main::DepotType{$sp}}[0] == 2) and push @sorted, $sp;
  5673. }
  5674. $main::V3 and do
  5675. {
  5676. print "\nsorted depots:\n";
  5677. foreach $sp (@sorted)
  5678. {
  5679. printf " %20s %s\n", @{$main::DepotType{$sp}}[1], $sp;
  5680. }
  5681. };
  5682. return @sorted;
  5683. }
  5684. # _____________________________________________________________________________
  5685. #
  5686. # VerifyBranch
  5687. #
  5688. # Parameters:
  5689. #
  5690. # Output:
  5691. # _____________________________________________________________________________
  5692. sub VerifyBranch
  5693. {
  5694. my $enlisting = ($_[0] eq "enlist");
  5695. my $defecting = ($_[0] eq "defect");
  5696. my $repairing = ($_[0] eq "repair");
  5697. my $nd = $_[1];
  5698. my @depots = ();
  5699. printf "\nLooking for branch %s in the depot%s", "\U$main::Branch", $nd > 1 ? "s" : "";
  5700. $enlisting and @depots = @main::EnlistDepots;
  5701. $defecting and @depots = @main::DefectDepots;
  5702. my $warning = $main::FALSE;
  5703. foreach $depot (@depots)
  5704. {
  5705. print ".";
  5706. my $serverport = @$depot[0];
  5707. !grep(/Branch $main::Branch /, `sd.exe -p $serverport branches 2>&1`) and $warning = $main::TRUE;
  5708. }
  5709. !$warning and print "\nok.\n";
  5710. return $warning;
  5711. }
  5712. # _____________________________________________________________________________
  5713. #
  5714. # VerifyClient
  5715. #
  5716. # Parameters:
  5717. #
  5718. # Output:
  5719. # _____________________________________________________________________________
  5720. sub VerifyClient
  5721. {
  5722. my $client = "\U$main::SDClient";
  5723. print "\nChecking for client $client in the depots.";
  5724. foreach $depot (@main::AllDepots)
  5725. {
  5726. print ".";
  5727. my $serverport = @$depot[0];
  5728. if (SDX::ClientExists($serverport, $main::SDClient))
  5729. {
  5730. print "\n\n$client already exists. Enlisting with \@<client> is only supported for new\n";
  5731. print "enlistents. If you want to keep $client as your client name, run 'sdx defect\n";
  5732. print "$main::CodeBase $main::Branch -a -f' to defect, or set \%SDCLIENT\% to another\n";
  5733. print "name, then rerun this command.\n";
  5734. die("\n");
  5735. }
  5736. }
  5737. print "\nok.\n";
  5738. };
  5739. # _____________________________________________________________________________
  5740. #
  5741. # GetProjectsToRepair
  5742. #
  5743. # Parameters:
  5744. #
  5745. # Output:
  5746. # populates @main::RepairDepots and @main::RepairProjects
  5747. # returns 1 if successful, 0 otherwise
  5748. # _____________________________________________________________________________
  5749. sub GetProjectsToRepair
  5750. {
  5751. @main::RepairDepots = ();
  5752. @main::RepairProjects = ();
  5753. %seen = ();
  5754. #
  5755. # if only rewriting SD.INIs, base the depot/project repair lists on
  5756. # whatever is in SD.MAP and the codebase map
  5757. #
  5758. if ($main::MinusI)
  5759. {
  5760. my %seen = ();
  5761. #
  5762. # build list of depots
  5763. #
  5764. for $proj (@main::SDMapProjects)
  5765. {
  5766. for $proj2 (@main::AllProjects)
  5767. {
  5768. (@$proj[$main::CBMProjectField] eq @$proj2[$main::CBMProjectField]) and do
  5769. {
  5770. push @main::RepairProjects, $proj2;
  5771. my $sp = @$proj2[$main::CBMServerPortField];
  5772. unless ($seen{$sp})
  5773. {
  5774. $seen{$sp} = 1;
  5775. push @main::RepairDepots, [("$sp", "@$proj2[$main::CBMDepotNameField]")];
  5776. }
  5777. }
  5778. }
  5779. }
  5780. #
  5781. # adjust the list of actively used depots to
  5782. # reflect what we got out of the codebase map
  5783. #
  5784. @main::ActiveDepots = ();
  5785. for $depot (@main::RepairDepots)
  5786. {
  5787. push @main::ActiveDepots, @$depot[0];
  5788. };
  5789. }
  5790. else
  5791. {
  5792. #
  5793. # for each depot, see if the client exists
  5794. # if so, get its view and munge it to see which
  5795. # projects it includes
  5796. #
  5797. foreach $depot (@main::AllDepots)
  5798. {
  5799. $serverport = @$depot[0];
  5800. $main::V3 and print "\t$serverport\n";
  5801. if (SDX::ClientExists($serverport, $main::SDClient))
  5802. {
  5803. #
  5804. # add this depot to the list
  5805. #
  5806. push @main::RepairDepots, $depot;
  5807. #
  5808. # read the existing client view into @main::ExistingView
  5809. #
  5810. SDX::GetClientView("repair", $serverport, $main::SDClient);
  5811. foreach $line (@main::ExistingView)
  5812. {
  5813. #
  5814. # throw away negating view lines
  5815. #
  5816. $line =~ /^[\t\s]+-/ and next;
  5817. @fields = split(/\//, $line);
  5818. $branch = @fields[3];
  5819. $project = @fields[4];
  5820. $project and do
  5821. {
  5822. # print "b/p $branch $project\n";
  5823. for $projectline (@main::AllProjects)
  5824. {
  5825. if ("\U$project" eq "\U@$projectline[$main::CBMProjectField]")
  5826. {
  5827. unless ($seen{$project})
  5828. {
  5829. $seen{$project} = 1;
  5830. push @main::RepairProjects, $projectline;
  5831. }
  5832. last;
  5833. }
  5834. }
  5835. };
  5836. }
  5837. }
  5838. }
  5839. }
  5840. $main::V3 and do
  5841. {
  5842. foreach $depot (@main::RepairDepots)
  5843. {
  5844. print "RepairDepots: @$depot\n";
  5845. }
  5846. print "\n";
  5847. foreach $project (@main::RepairProjects)
  5848. {
  5849. print "RepairProjects: @$project\n";
  5850. }
  5851. };
  5852. #
  5853. # verify access for all depots in the repair list
  5854. #
  5855. @main::VerifyDepots = @main::RepairDepots;
  5856. #
  5857. # return success as long as these two lists have values
  5858. #
  5859. (@main::RepairDepots && @main::RepairProjects) and return 1;
  5860. return 0;
  5861. }
  5862. # _____________________________________________________________________________
  5863. #
  5864. # CreateView
  5865. #
  5866. # Parameters:
  5867. # Command Line Arguments
  5868. #
  5869. # Output:
  5870. #
  5871. # _____________________________________________________________________________
  5872. sub CreateView
  5873. {
  5874. $depot = $_[0];
  5875. my $enlisting = ($_[1] eq "enlist");
  5876. my $defecting = ($_[1] eq "defect");
  5877. my $repairing = ($_[1] eq "repair");
  5878. my $root = "";
  5879. my $clobber = $main::FALSE;
  5880. $serverport = @$depot[0];
  5881. $depotname = @$depot[1];
  5882. @main::tmpView = ();
  5883. @main::FinalView = ();
  5884. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in CreateView().\n");
  5885. unlink $main::ClientView;
  5886. #
  5887. # write the default view lines for this depot and project(s)
  5888. #
  5889. SDX::WriteDefaultView($serverport, $depotname);
  5890. #
  5891. # if we're doing a clean enlist or the client doesn't already exist,
  5892. # use the default view
  5893. # else merge the default view with the existing view
  5894. #
  5895. if ($main::CleanEnlist or !SDX::ClientExists($serverport, $main::SDClient))
  5896. {
  5897. #
  5898. # Root: field for client view depends on depot type
  5899. #
  5900. # for type 1 (1 project/depot), root includes project name
  5901. # for type 2 (N projects/depot), root is just main::SDXRoot
  5902. #
  5903. # root is at least SDXRoot in either case
  5904. #
  5905. $root = $main::SDXRoot;
  5906. (@{$main::DepotType{$serverport}}[0] == 1) and $root = SDX::Type1Root($root);
  5907. #
  5908. # files in root project in NT are clobberable
  5909. #
  5910. # BUGBUG-2000/5/12-jeffmcd -- this should be an option in the codebase map -- ClobberRoot = 1 or 0
  5911. #
  5912. if ("\U$main::CodeBase" eq "NT")
  5913. {
  5914. $project = @main::ProjectsInThisDepot[0];
  5915. $clobber = ("\L@$project[$main::CBMProjectField]" eq "root");
  5916. }
  5917. #
  5918. # write default view header
  5919. #
  5920. open(CLIENTVIEW, ">$main::ClientView") or die("\nCan't open $main::ClientView for writing.\n");
  5921. printf CLIENTVIEW "Client: %s\n\n", $main::SDClient;
  5922. printf CLIENTVIEW "Owner: %s\n\n", $main::SDDomainUser;
  5923. printf CLIENTVIEW "Description:\n Created by %s.\n\n", $main::SDDomainUser;
  5924. printf CLIENTVIEW "Root: %s\n\n", $root;
  5925. printf CLIENTVIEW "Options: noallwrite %sclobber nocompress nocrlf locked nomodtime\n\n", $clobber ? "" : "no";
  5926. printf CLIENTVIEW "View:\n";
  5927. #
  5928. # append the default view
  5929. #
  5930. for $line (@main::DefaultView)
  5931. {
  5932. printf CLIENTVIEW $line;
  5933. ### push @clientview, $line;
  5934. }
  5935. close(CLIENTVIEW);
  5936. $verb = "Creating";
  5937. }
  5938. else
  5939. {
  5940. #
  5941. # read the existing client view into @main::ExistingView
  5942. #
  5943. SDX:GetClientView("enlist", $serverport, $main::SDClient);
  5944. #
  5945. # concat the existing view and the default view
  5946. #
  5947. for $line (@main::ExistingView)
  5948. {
  5949. push @main::tmpView, $line;
  5950. }
  5951. for $line (@main::DefaultView)
  5952. {
  5953. push @main::tmpView, $line;
  5954. }
  5955. $main::V3 and do
  5956. {
  5957. print "\nexisting + default:\n";
  5958. print @main::tmpView;
  5959. };
  5960. #
  5961. # sort the list for uniqueness, preserving order
  5962. #
  5963. %seen = ();
  5964. @uniq = ();
  5965. foreach $line (@main::tmpView)
  5966. {
  5967. #
  5968. # lowercase the line for the check, but push the
  5969. # unchanged version of line onto the list so
  5970. # we preserve the user's case
  5971. #
  5972. unless ($seen{"\L$line"})
  5973. {
  5974. $seen{"\L$line"} = 1;
  5975. push @uniq, $line;
  5976. }
  5977. }
  5978. @main::FinalView = @uniq;
  5979. $main::V3 and do
  5980. {
  5981. print "\nfinal view:\n";
  5982. print @main::FinalView;
  5983. };
  5984. #
  5985. # now finish writing the client view by appending the
  5986. # final view spec
  5987. #
  5988. open(CLIENTVIEW, ">>$main::ClientView") or die("\nCan't open $main::ClientView for writing.\n");
  5989. for $viewline (@main::FinalView)
  5990. {
  5991. printf CLIENTVIEW $viewline;
  5992. }
  5993. close(CLIENTVIEW);
  5994. $verb = "Updating existing";
  5995. $repairing and $verb = "Verifying";
  5996. }
  5997. printf "\n%s client %s in depot %s.\n", $verb, $main::SDClient, $serverport;
  5998. $main::V1 and do
  5999. {
  6000. $main::V2 and do
  6001. {
  6002. printf "\ndepot mapping for %s (//%s) consists of %s project(s):\n\n", $serverport, $depotname, $#main::ProjectsInThisDepot+1;
  6003. foreach $project (@main::ProjectsInThisDepot)
  6004. {
  6005. printf "\t%s\n", @$project[$main::CBMProjectField];
  6006. }
  6007. };
  6008. print "\n\n";
  6009. system "type $main::ClientView 2>&1";
  6010. print "\n--------------------------------------------------\n\n";
  6011. };
  6012. }
  6013. # _____________________________________________________________________________
  6014. #
  6015. # WriteDefaultView
  6016. #
  6017. # Create the default view lines for this depot/project and push them onto a list
  6018. #
  6019. # Parameters:
  6020. #
  6021. # Output:
  6022. #
  6023. # _____________________________________________________________________________
  6024. sub WriteDefaultView()
  6025. {
  6026. $serverport = $_[0];
  6027. $depotname = $_[1];
  6028. $proj = "";
  6029. $group = "";
  6030. $projroot = "";
  6031. @main::DefaultView = ();
  6032. $main::V3 and do
  6033. {
  6034. print "sp = '$serverport'\n";
  6035. print "depotname = '$depotname'\n";
  6036. };
  6037. #
  6038. # for each project in this depot, generate the depot mappings and push
  6039. # them onto a list
  6040. #
  6041. foreach $project (@main::ProjectsInThisDepot)
  6042. {
  6043. $usingroot = $main::FALSE;
  6044. $proj = @$project[$main::CBMProjectField];
  6045. $group = @$project[$main::CBMGroupField];
  6046. $projroot = @$project[$main::CBMProjectRootField];
  6047. #
  6048. # flip any '\' in the proj root path into '/' for SD
  6049. #
  6050. $projroot =~ s/\\/\//g;
  6051. #
  6052. # special case for enlisting a project directly in the root
  6053. #
  6054. if ($projroot eq "sdxroot")
  6055. {
  6056. $usingroot = $main::TRUE;
  6057. }
  6058. #
  6059. # if no project root was given in the codebase map,
  6060. # assume the root is same as the project name
  6061. #
  6062. if (!$projroot)
  6063. {
  6064. $projroot = $proj;
  6065. }
  6066. #
  6067. # create and save the view line for this project
  6068. #
  6069. # handle special case for SD sources
  6070. # handle special case for enlisting directly in %SDXROOT%
  6071. # otherwise handle normal case
  6072. #
  6073. #
  6074. # see if this project is one for which we should exclude
  6075. # some platform-specific dirs from its view
  6076. #
  6077. $found = $main::FALSE;
  6078. $Exclude = $main::FALSE;
  6079. foreach $someproj (@main::PlatformProjects)
  6080. {
  6081. if ("\U$proj" eq "\U$someproj")
  6082. {
  6083. $found = $main::TRUE;
  6084. }
  6085. }
  6086. if ($found && $main::Exclusions)
  6087. {
  6088. $Exclude = $main::TRUE;
  6089. if ("\U$main::Platform" eq "X86")
  6090. {
  6091. }
  6092. if ("\U$main::Platform" eq "AMD64")
  6093. {
  6094. @ExcludePlats = ("x86", "i386", "ia64");
  6095. }
  6096. if ("\U$main::Platform" eq "IA64")
  6097. {
  6098. @ExcludePlats = ("x86", "i386", "amd64");
  6099. }
  6100. }
  6101. #
  6102. # special case for handling the one project in the codebase map that can be enlisted directly
  6103. # in $main::SDXRoot
  6104. #
  6105. if ($usingroot)
  6106. {
  6107. $projroot = $proj;
  6108. #
  6109. # maybe restrict the scope of the root mapping
  6110. #
  6111. $rootspec = "...";
  6112. $main::RestrictRoot and do
  6113. {
  6114. $rootspec = "*";
  6115. };
  6116. #
  6117. # generate some shorthand for the depot-branch-project on LHS of the view
  6118. #
  6119. my $dbp = SDX::MakeDBP($serverport, $depotname, $group, $projroot);
  6120. #
  6121. # if this is the tools project and the user wants the minimal
  6122. # tool set, customize the view
  6123. #
  6124. # else generate the normal view line
  6125. #
  6126. my $mintools = ("\U$proj" eq "\U$main::ToolsProject" and $main::MinimalTools);
  6127. if ($mintools)
  6128. {
  6129. #
  6130. # add '/' if we have a tools path
  6131. #
  6132. my $tpath = ($main::ToolsPath ? "/$main::ToolsPath" : "");
  6133. #
  6134. # flip any '\' in the tools path into '/' for SD
  6135. #
  6136. $tpath =~ s/\\/\//g;
  6137. #
  6138. # -//depot/<branch>/<toolsproj>/... //<client>/...
  6139. #
  6140. $viewline = sprintf("\t-//%s/... //%s/...\n", $dbp, $main::SDClient);
  6141. push @main::DefaultView, $viewline;
  6142. #
  6143. # //depot/<branch>/<toolsproj>/* //<client>/*
  6144. #
  6145. $viewline = sprintf("\t//%s/* //%s/*\n", $dbp, $main::SDClient);
  6146. push @main::DefaultView, $viewline;
  6147. #
  6148. # //depot/<branch>/<toolsproj>[/<toolspath>/]* //<client>[/<toolspath>/]*
  6149. #
  6150. $viewline = sprintf("\t//%s%s/* //%s%s/*\n", $dbp, $tpath, $main::SDClient, $tpath);
  6151. push @main::DefaultView, $viewline;
  6152. #
  6153. # //depot/<branch>/<toolsproj>[/<toolspath>]/<PA>/*sd*exe //<client>[/<toolspath>]/<PA>/*sd*exe
  6154. #
  6155. $viewline = sprintf("\t//%s%s/%s/*sd*exe //%s%s/%s/*sd*exe\n", $dbp, $tpath, $main::Platform, $main::SDClient, $tpath, $main::Platform);
  6156. push @main::DefaultView, $viewline;
  6157. #
  6158. # //depot/<branch>/<toolsproj>[/<toolspath>]/<PA>/perl/... //<client>[/<toolspath>]/<PA>/perl/...
  6159. #
  6160. $viewline = sprintf("\t//%s%s/%s/perl/... //%s%s/%s/perl/...\n", $dbp, $tpath, $main::Platform, $main::SDClient, $tpath, $main::Platform);
  6161. push @main::DefaultView, $viewline;
  6162. }
  6163. else
  6164. {
  6165. $viewline = sprintf("\t//%s/%s //%s/%s\n", $dbp, $rootspec, $main::SDClient, $rootspec);
  6166. push @main::DefaultView, $viewline;
  6167. }
  6168. #
  6169. # if it's NT (or a codebase that uses NT's Root depot) and exclusionary mappings are allowed,
  6170. # restrict the user's view of \developer to just themselves
  6171. #
  6172. $main::Exclusions and do
  6173. {
  6174. ### HACKHACK -- rm check on $main::RestrictRoot when old NTTEST CBM goes away
  6175. #
  6176. # BUGBUG-2000/01/18-jeffmcd -- add keyword USERSDIR=<some dir relative to root containing user-specific files>
  6177. #
  6178. (
  6179. "\U$main::CodeBase" eq "NT" or
  6180. ("\U$main::CodeBase" eq "NTTEST" and !$main::RestrictRoot) or
  6181. "\U$main::CodeBase" eq "NTSDK" or
  6182. "\U$main::CodeBase" eq "NT.INTL" or
  6183. "\U$main::CodeBase" eq "MPC" or
  6184. "\U$main::CodeBase" eq "NGWS" or
  6185. "\U$main::CodeBase" eq "MGMT" or
  6186. "\U$main::CodeBase" eq "MOM" or
  6187. "\U$main::CodeBase" eq "PDDEPOT" or
  6188. "\U$main::CodeBase" eq "WINMEDIA"
  6189. ) and do
  6190. {
  6191. #
  6192. # this negation line isn't necessary if we're doing minimal tools
  6193. #
  6194. !$mintools and do
  6195. {
  6196. $viewline = sprintf("\t-//%s/developer/... //%s/developer/...\n", $dbp, $main::SDClient);
  6197. push @main::DefaultView, $viewline;
  6198. };
  6199. $viewline = sprintf("\t//%s/developer/* //%s/developer/*\n", $dbp, $main::SDClient);
  6200. push @main::DefaultView, $viewline;
  6201. $viewline = sprintf("\t//%s/developer/%s/... //%s/developer/%s/...\n", $dbp, $main::SDUser, $main::SDClient, $main::SDUser);
  6202. push @main::DefaultView, $viewline;
  6203. };
  6204. };
  6205. #
  6206. # only do the exclude lines if the root isn't already restricted
  6207. # and we're not doing minimal tools (since everything in Root will
  6208. # already be restricted except what the user needs)
  6209. #
  6210. if ($Exclude && !$main::RestrictRoot && !$main::MinimalTools)
  6211. {
  6212. for $e (@ExcludePlats)
  6213. {
  6214. #
  6215. # generate the view line and save it away
  6216. #
  6217. $viewline = sprintf("\t-//%s/.../%s/... //%s/.../%s/...\n", $dbp, $e, $main::SDClient, $e);
  6218. push @main::DefaultView, $viewline;
  6219. }
  6220. }
  6221. }
  6222. else
  6223. {
  6224. #
  6225. # generate the view line(s)
  6226. #
  6227. #
  6228. # for the USERS project in Scratch depots, only map in \users\<this user>
  6229. #
  6230. # BUGBUG-2000/01/10-jeffmcd -- remove this when enlisting with <project>\path\path\path is supported
  6231. #
  6232. if ("\U$main::CodeBase" eq "SCRATCH" and $projroot eq "users")
  6233. {
  6234. # shorthand
  6235. my $dbp = SDX::MakeDBP($serverport, $depotname, $group, $projroot);
  6236. # -//depot/<branch>/users/... //<client>/users/...
  6237. $viewline = sprintf("\t-//%s/... //%s/%s/...\n", $dbp, $main::SDClient, $projroot);
  6238. push @main::DefaultView, $viewline;
  6239. # //depot/<branch>/users/<this user>/... //<client>/users/<this user>/...
  6240. $viewline = sprintf("\t//%s/%s/... //%s/%s/%s/...\n", $dbp, $main::SDUser, $main::SDClient, $projroot, $main::SDUser);
  6241. push @main::DefaultView, $viewline;
  6242. }
  6243. else
  6244. {
  6245. #
  6246. # the form of the project root depends on project type and codebase
  6247. #
  6248. my $proot = SDX::MakeProjectRoot($proj, $projroot);
  6249. #
  6250. # some shorthand
  6251. #
  6252. my $dbp = SDX::MakeDBP($serverport, $depotname, $group, $proj);
  6253. my $mintools = ("\U$main::ToolsProject" eq "\U$proj" and $main::MinimalTools);
  6254. #
  6255. # if $proj is the tools project and the user wants the minimal
  6256. # tool set, customize the view
  6257. #
  6258. # else generate the normal view line
  6259. #
  6260. if ($mintools)
  6261. {
  6262. #
  6263. # add '/' if we have a tools path
  6264. # add "/<project root>" if type 2 depot
  6265. #
  6266. my $tpath = ($main::ToolsPath ? "/$main::ToolsPath" : "");
  6267. #
  6268. # flip any '\' in the tools path into '/' for SD
  6269. #
  6270. $tpath =~ s/\\/\//g;
  6271. #
  6272. # 1: -//depot/<branch>/<proj>/... //<client>/...
  6273. # 2: -//depot/<branch>/<proj>/... //<client>/<project root>/...
  6274. #
  6275. $viewline = sprintf("\t-//%s/... //%s%s/...\n", $dbp, $main::SDClient, $proot);
  6276. push @main::DefaultView, $viewline;
  6277. #
  6278. # 1: //depot/<branch>/<proj>/<toolspath>/* //<client>/<toolspath>/*
  6279. # 2: //depot/<branch>/<proj>/<toolspath>/* //<client>/<project root>/<toolspath>/*
  6280. #
  6281. $viewline = sprintf("\t//%s%s/* //%s%s%s/*\n", $dbp, $tpath, $main::SDClient, $proot, $tpath);
  6282. push @main::DefaultView, $viewline;
  6283. #
  6284. # 1: //depot/<branch>/<proj>/<toolspath>/<PA>/*sd*exe //<client>/<toolspath>/<PA>/*sd*exe
  6285. # 2: //depot/<branch>/<proj>/<toolspath>/<PA>/*sd*exe //<client>/<project root>/<toolspath>/<PA>/*sd*exe
  6286. #
  6287. $viewline = sprintf("\t//%s%s/%s/*sd*exe //%s%s%s/%s/*sd*exe\n", $dbp, $tpath, $main::Platform, $main::SDClient, $proot, $tpath, $main::Platform);
  6288. push @main::DefaultView, $viewline;
  6289. #
  6290. # 1: //depot/<branch>/<proj>/<toolspath>/<PA>/perl/... //<client>/<toolspath>/<PA>/perl/...
  6291. # 2: //depot/<branch>/<proj>/<toolspath>/<PA>/perl/... //<client>/<project root>/<toolspath>/<PA>/perl/...
  6292. #
  6293. $viewline = sprintf("\t//%s%s/%s/perl/... //%s%s%s/%s/perl/...\n", $dbp, $tpath, $main::Platform, $main::SDClient, $proot, $tpath, $main::Platform);
  6294. push @main::DefaultView, $viewline;
  6295. }
  6296. else
  6297. {
  6298. #
  6299. # 1: //depot/<branch>/project/... //<client>/...
  6300. # 2: //depot/<branch>/<project>/... //<client>/<project root>/...
  6301. #
  6302. $viewline = sprintf("\t//%s/... //%s%s/...\n", $dbp, $main::SDClient, $proot);
  6303. push @main::DefaultView, $viewline;
  6304. }
  6305. }
  6306. #
  6307. # add exclude lines to the view if this project is marked as
  6308. # having multiple platforms in the codebase map
  6309. #
  6310. if ($Exclude)
  6311. {
  6312. # shorthand
  6313. my $dbp = "$depotname/$main::Branch/$proj";
  6314. for $e (@ExcludePlats)
  6315. {
  6316. #
  6317. # generate the view line and save it away
  6318. #
  6319. # for type 1 projects (1 project/depot) project name can't be in RHS
  6320. #
  6321. # for type 2 projects (N projects/depot) project name must be in RHS
  6322. #
  6323. my $proot = SDX::MakeProjectRoot($proj, $projroot);
  6324. $viewline = sprintf("\t-//%s/.../%s/... //%s%s/.../%s/...\n", $dbp, $e, $main::SDClient, $proot, $e);
  6325. push @main::DefaultView, $viewline;
  6326. }
  6327. }
  6328. }
  6329. }
  6330. $main::V2 and do
  6331. {
  6332. print "\ndefault view --------------------\n";
  6333. for $line (@main::DefaultView)
  6334. {
  6335. print "$line";
  6336. }
  6337. print "---------------------------------\n";
  6338. };
  6339. }
  6340. # _____________________________________________________________________________
  6341. #
  6342. # MakeDBP
  6343. #
  6344. # builds depot-branch-project string depending on project's group
  6345. #
  6346. # Parameters:
  6347. #
  6348. # Output:
  6349. #
  6350. # string
  6351. #
  6352. # _____________________________________________________________________________
  6353. sub MakeDBP()
  6354. {
  6355. my $sp = $_[0];
  6356. my $depotname = $_[1];
  6357. my $group = $_[2];
  6358. my $projroot = $_[3];
  6359. my $path = "//$depotname/$main::Branch/$projroot";
  6360. $main::V3 and do
  6361. {
  6362. print "\nmakedbp: sp = '$sp'\n";
  6363. print "makedbp: depotname = '$depotname'\n";
  6364. print "makedbp: group = '$group'\n";
  6365. print "makedbp: projroot = '$projroot'\n\n";
  6366. print "makedbp: path = '$path'\n\n";
  6367. };
  6368. #
  6369. # start with depot name
  6370. #
  6371. my $dbp = $depotname;
  6372. #
  6373. # determine branch
  6374. #
  6375. # NTDEV projects have lab branches, so we can use whichever one the user wants
  6376. #
  6377. # non-NTDEV projects (like Test, Spec, Intl projects) may or may not have the
  6378. # user's lab branch -- if it exists, use it, else default to the master branch
  6379. #
  6380. if (("\U$group" eq "NTDEV") or (SDX::BranchExists($main::Branch, $sp, $path, "by-path")))
  6381. {
  6382. $dbp .= "/$main::Branch/";
  6383. }
  6384. else
  6385. {
  6386. $dbp .= "/$main::MasterBranch/";
  6387. }
  6388. #
  6389. # add the project root
  6390. #
  6391. $dbp .= $projroot;
  6392. $main::V3 and print "makedbp: returning '$dbp'\n";
  6393. return $dbp;
  6394. }
  6395. # _____________________________________________________________________________
  6396. #
  6397. # ClientExists
  6398. #
  6399. # Determine if $main::SDClient exists in the given depot
  6400. #
  6401. # Parameters:
  6402. #
  6403. # Output:
  6404. #
  6405. # TRUE if client found in depot, FALSE otherwise
  6406. # _____________________________________________________________________________
  6407. sub ClientExists()
  6408. {
  6409. my $serverport = $_[0];
  6410. my $client = $_[1];
  6411. my @out = ();
  6412. my $found = $main::FALSE;
  6413. #
  6414. # list clients and grep for client name
  6415. #
  6416. @out = `sd.exe -p $serverport clients 2>&1`;
  6417. (grep /Client $client /i, @out) and $found = $main::TRUE;
  6418. #
  6419. # die if we're ever denied access
  6420. #
  6421. SDX::AccessDenied(\@out, $serverport) and die("\n");
  6422. return $found;
  6423. }
  6424. # _____________________________________________________________________________
  6425. #
  6426. # BranchExists
  6427. #
  6428. # Determine if a branch exists in the given depot
  6429. #
  6430. # Parameters:
  6431. #
  6432. # Output:
  6433. #
  6434. # TRUE if found, FALSE otherwise
  6435. # _____________________________________________________________________________
  6436. sub BranchExists()
  6437. {
  6438. my $branch = $_[0];
  6439. my $sp = "-p $_[1]";
  6440. my $path = $_[2];
  6441. my $method = $_[3];
  6442. $main::V2 and do
  6443. {
  6444. print "\nbranchexists: branch = '$branch'\n";
  6445. print "branchexists: sp = '$sp'\n";
  6446. print "branchexists: path = '$path'\n";
  6447. print "branchexists: method = '$method'\n\n";
  6448. };
  6449. #
  6450. # list branches and look for branch name
  6451. #
  6452. ($method eq "by-name") and do
  6453. {
  6454. grep(/Branch $branch/i, `sd.exe $sp branches 2>&1`) and return 1;
  6455. };
  6456. #
  6457. # see if //<depot>/<branch>/<project> is found
  6458. #
  6459. # sd dirs is unreliable, so look at the first line returned by sd files ...
  6460. #
  6461. ($method eq "by-path") and do
  6462. {
  6463. my @out = ();
  6464. open FILE, "sd.exe $sp files $path/... 2>&1 |" or die("\nBranchExists: can't open pipe.\n");
  6465. while (<FILE>) { push @out, $_; last; }
  6466. close FILE;
  6467. grep(/ no such /, @out) and return 0;
  6468. return 1;
  6469. };
  6470. return 0;
  6471. }
  6472. # _____________________________________________________________________________
  6473. #
  6474. # GetClientView
  6475. #
  6476. # Read the existing client view out of the depot for this client. Split it into
  6477. # header and view lines. If enlisting/defecting, write the header directly to the
  6478. # new client view file.
  6479. #
  6480. # Parameters:
  6481. # serverport depot server:port pair
  6482. # client SDClient name to look up
  6483. #
  6484. # Output:
  6485. # populates @main::ExistingView if repairing
  6486. # writes $main::ClientView if enlisting/defecting
  6487. # _____________________________________________________________________________
  6488. sub GetClientView()
  6489. {
  6490. my $enlisting = ($_[0] eq "enlist");
  6491. my $defecting = ($_[0] eq "defect");
  6492. my $repairing = ($_[0] eq "repair");
  6493. my @view = ();
  6494. $serverport = $_[1];
  6495. $client = $_[2];
  6496. @main::ExistingView = ();
  6497. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in GetClientView().\n");
  6498. #
  6499. # dump the client view spec
  6500. #
  6501. @view = `sd.exe -p $serverport client -o $client 2>&1`;
  6502. #
  6503. # read the viewspec and maybe write the header for the new client view
  6504. #
  6505. ($enlisting || $defecting) and (open(CLIENTVIEW, ">$main::ClientView") or die("\nCan't open $main::ClientView for writing.\n"));
  6506. $header = $main::TRUE;
  6507. foreach $line (@view)
  6508. {
  6509. #
  6510. # throw away comments and blank lines
  6511. #
  6512. $line =~ /^#/ and next;
  6513. $line =~ /^[\t\s]*$/ and next;
  6514. #
  6515. # if we're still in the header, right the line directly
  6516. # to the new view
  6517. # otherwise push the view line into a list for later use
  6518. #
  6519. if ($header)
  6520. {
  6521. ($enlisting || $defecting) and printf CLIENTVIEW $line;
  6522. }
  6523. else
  6524. {
  6525. push @main::ExistingView, $line;
  6526. }
  6527. @vline = split(/[\t\s]+/,$line);
  6528. if ("\U$vline[0]" eq "VIEW:")
  6529. {
  6530. $header = $main::FALSE;
  6531. }
  6532. }
  6533. ($enlisting || $defecting) and close(CLIENTVIEW);
  6534. $main::V3 and do
  6535. {
  6536. # print "\nexisting view header:\n";
  6537. # system "type $main::ClientView";
  6538. print "\nexisting view -------------------\n";
  6539. print "'@main::ExistingView'\n";
  6540. print "---------------------------------\n";
  6541. };
  6542. }
  6543. # _____________________________________________________________________________
  6544. #
  6545. # UpdateSDMap
  6546. #
  6547. # Creates or updates %SDXROOT%\SD.MAP, containing a list of projects and relative
  6548. # paths to their roots in the enlistment where the SD.INI can be found.
  6549. #
  6550. # Leaves these files read-only so they stay nailed down when we delete /S.
  6551. #
  6552. # Parameters:
  6553. #
  6554. # Output:
  6555. # _____________________________________________________________________________
  6556. sub UpdateSDMap
  6557. {
  6558. my $op = $_[0];
  6559. my $enlisting = ($op eq "enlist");
  6560. my $defecting = ($op eq "defect");
  6561. my $repairing = ($op eq "repair");
  6562. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in UpdateSDMap().\n");
  6563. @main::tmpMap = ();
  6564. #
  6565. # if we're doing a clean enlist (ie no SD.MAP exists), use the default map
  6566. # else merge the default map with the existing map
  6567. #
  6568. ($enlisting || $repairing) and do
  6569. {
  6570. if (!(-e $main::SDMap))
  6571. {
  6572. printf "%s SD.MAP", $enlisting ? "Creating" : "Restoring";
  6573. @null = ();
  6574. SDX::WriteSDMap(\@null);
  6575. print "\n";
  6576. }
  6577. else
  6578. {
  6579. printf "%s SD.MAP", $enlisting ? "Updating" : "Repairing";
  6580. #
  6581. # load the default map into @main::DefaultMap
  6582. # and write the SD.INIs
  6583. #
  6584. SDX:WriteDefaultMap($main::Null, $main::Null);
  6585. #
  6586. # load the existing map into @main::ExistingMap
  6587. #
  6588. SDX::GetMapProjects($op);
  6589. #
  6590. # concat these two lists
  6591. #
  6592. for $line (@main::DefaultMap)
  6593. {
  6594. push @main::tmpMap, $line;
  6595. }
  6596. for $line (@main::ExistingMap)
  6597. {
  6598. push @main::tmpMap, $line;
  6599. }
  6600. $main::V1 and do
  6601. {
  6602. print "\ntmp map:\n\t";
  6603. print @main::tmpMap;
  6604. };
  6605. #
  6606. # unique-ify and sort them
  6607. #
  6608. %seen = ();
  6609. foreach $line (@main::tmpMap)
  6610. {
  6611. $seen{$line}++;
  6612. }
  6613. @uniq = keys %seen;
  6614. $main::V1 and do
  6615. {
  6616. print "\nuniq map:\n\t";
  6617. print @uniq;
  6618. };
  6619. @sorted = sort @uniq;
  6620. $main::V3 and do
  6621. {
  6622. print "\nsorted:\n\t";
  6623. print @sorted;
  6624. };
  6625. #
  6626. # write it
  6627. #
  6628. SDX::WriteSDMap(\@sorted);
  6629. print "\n";
  6630. }
  6631. };
  6632. $defecting and do
  6633. {
  6634. if ($main::DefectAll)
  6635. {
  6636. SDX::KillSDMap();
  6637. }
  6638. else
  6639. {
  6640. print "Removing projects from SD.MAP";
  6641. #
  6642. # load the default map into @main::DefaultMap
  6643. #
  6644. SDX:WriteDefaultMap($main::Null,$main::Null);
  6645. #
  6646. # load the existing map into @main::ExistingMap
  6647. #
  6648. if (SDX::GetMapProjects($op))
  6649. {
  6650. #
  6651. # use the existing map lines as keys to a hash,
  6652. # lowercasing them to ignore upper/lowercase
  6653. # distinctions
  6654. #
  6655. # for each line in the default map, mark it as
  6656. # removed from the hash of existing lines
  6657. #
  6658. # write the unmarked hash lines back into the list
  6659. # and sort it
  6660. #
  6661. @tmpmap = ();
  6662. %existingmap = ();
  6663. foreach $em (@main::ExistingMap)
  6664. {
  6665. $existingmap{"\L$em"} = 1;
  6666. }
  6667. $main::V3 and do
  6668. {
  6669. print "\n\nexistingmap:\n";
  6670. while (($k,$v) = each %existingmap)
  6671. {
  6672. printf "%40s %s\n", $k, $v;
  6673. }
  6674. };
  6675. foreach $dm (@main::DefaultMap)
  6676. {
  6677. if ($existingmap{"\L$dm"} == 1)
  6678. {
  6679. $existingmap{"\L$dm"} = 0;
  6680. }
  6681. }
  6682. $main::V2 and print "\nexistingmap, edited:\n";
  6683. while (($k,$v) = each %existingmap)
  6684. {
  6685. $v and push @tmpmap, $k;
  6686. $main::V2 and do
  6687. {
  6688. my $vv = (!$v) ? " $v" : $v;
  6689. printf "%40s %s\n", $k, $vv;
  6690. }
  6691. }
  6692. @sorted = sort @tmpmap;
  6693. $main::V3 and do
  6694. {
  6695. print "\nsorted:\n\t";
  6696. print @sorted;
  6697. };
  6698. #
  6699. # at this point, if we still have something to write in the map file,
  6700. # write it out
  6701. # else remove whatever's left of it
  6702. #
  6703. # this will happen in the case where there are no DefaultProjects in
  6704. # the codebase map and the user lists all known projects on the defect
  6705. # cmd line
  6706. #
  6707. ($main::V3 and @sorted) and print "\n\t\@sorted not empty.\n";
  6708. ($main::V3 and !@sorted) and print "\n\t\@sorted empty.\n";
  6709. if (@sorted)
  6710. {
  6711. SDX::WriteSDMap(\@sorted);
  6712. print "\n";
  6713. }
  6714. else
  6715. {
  6716. SDX::KillSDMap();
  6717. }
  6718. }
  6719. }
  6720. };
  6721. #
  6722. # if we still have a map file, make it RO, hidden
  6723. #
  6724. (-e $main::SDMap) and system "attrib +R +H $main::SDMap >nul 2>&1";
  6725. }
  6726. # _____________________________________________________________________________
  6727. #
  6728. # WriteSDMap
  6729. #
  6730. # Parameters:
  6731. #
  6732. # Output:
  6733. # _____________________________________________________________________________
  6734. sub WriteSDMap
  6735. {
  6736. my ($sorted) = $_;
  6737. $main::V3 and print "\n\nwritesdmap: sorted = @sorted\n";
  6738. system "attrib -R -H -S $main::SDMap >nul 2>&1";
  6739. open(SDMAP, ">$main::SDMap") or die("\nCan't open $main::SDMap for writing.\n");
  6740. print SDMAP "#\n# SD.MAP -- autogenerated by SDX -- do not edit\n#\n";
  6741. print SDMAP "\nCODEBASE = $main::CodeBase\n";
  6742. SDX::WriteSDMapCodeBaseType($main::CodeBaseType, *SDMAP);
  6743. print SDMAP "BRANCH = $main::Branch\n";
  6744. print SDMAP "CLIENT = $main::SDClient\n";
  6745. print SDMAP "\n#\n# project root\n# ------------------- -----------------------------------------------------\n";
  6746. #
  6747. # if we have a sorted list of projects, print them,
  6748. # else write the default list
  6749. #
  6750. if (@sorted)
  6751. {
  6752. foreach $line (@sorted)
  6753. {
  6754. @fields = split(/=/, $line);
  6755. printf SDMAP "%21s = %-52s\n", $fields[0], $fields[1];
  6756. }
  6757. }
  6758. else
  6759. {
  6760. #
  6761. # append the default map lines to SD.MAP
  6762. #
  6763. SDX::WriteDefaultMap("append",*SDMAP);
  6764. }
  6765. #
  6766. # print the list of enlisted depots
  6767. #
  6768. SDX::WriteSDMapDepots(\@main::ActiveDepots, *SDMAP);
  6769. close(SDMAP);
  6770. }
  6771. # _____________________________________________________________________________
  6772. #
  6773. # WriteSDMapDepots
  6774. #
  6775. # add list of enlisted depots to SD.MAP
  6776. #
  6777. # Parameters:
  6778. #
  6779. # Output:
  6780. # _____________________________________________________________________________
  6781. sub WriteSDMapDepots
  6782. {
  6783. my ($depots) = $_[0];
  6784. my $sdmap = $_[1];
  6785. my $list = "";
  6786. for $d (@$depots)
  6787. {
  6788. $d =~ /\:/ and do
  6789. {
  6790. $list .= "$d ";
  6791. };
  6792. }
  6793. $main::V3 and do
  6794. {
  6795. print "\nabout to write depot list = '$list'\n";
  6796. };
  6797. print $sdmap "\n#\n# depots\n#\n";
  6798. print $sdmap "DEPOTS = $list\n\n";
  6799. }
  6800. # _____________________________________________________________________________
  6801. #
  6802. # WriteSDMapCodeBaseType
  6803. #
  6804. # add codebase type to SD.MAP
  6805. #
  6806. # Parameters:
  6807. #
  6808. # Output:
  6809. # _____________________________________________________________________________
  6810. sub WriteSDMapCodeBaseType
  6811. {
  6812. my $type = $_[0];
  6813. my $sdmap = $_[1];
  6814. print $sdmap "CODEBASETYPE = $type\n";
  6815. }
  6816. # _____________________________________________________________________________
  6817. #
  6818. # KillSDMap
  6819. #
  6820. # Parameters:
  6821. #
  6822. # Output:
  6823. # _____________________________________________________________________________
  6824. sub KillSDMap
  6825. {
  6826. -e $main::SDMap and do
  6827. {
  6828. print "Removing $main::SDMap\n";
  6829. system "attrib -R -H -S $main::SDMap >nul 2>&1";
  6830. unlink $main::SDMap;
  6831. };
  6832. }
  6833. # _____________________________________________________________________________
  6834. #
  6835. # WriteDefaultMap
  6836. # writes the project-specific SD.MAP lines to the actual SD.MAP (if enlisting
  6837. # clean) or pushes them onto a list so we can sort them later.
  6838. #
  6839. # Parameters:
  6840. #
  6841. # Output:
  6842. # _____________________________________________________________________________
  6843. sub WriteDefaultMap
  6844. {
  6845. my $appending = ($_[0] eq "append");
  6846. my $sdmap = $_[1];
  6847. @main::DefaultMap = ();
  6848. #
  6849. # maybe just append to the real SD.MAP, which at this point
  6850. # only contains the header
  6851. # otherwise write to a temp file
  6852. #
  6853. foreach $project (@main::ProjectsInThisDepot)
  6854. {
  6855. print ".";
  6856. $usingroot = $main::FALSE;
  6857. $proj = @$project[$main::CBMProjectField];
  6858. $serverport = @$project[$main::CBMServerPortField];
  6859. $projectroot = @$project[$main::CBMProjectRootField];
  6860. #
  6861. # if no project root was given in the codebase map,
  6862. # assume the root is same as the project name
  6863. #
  6864. if (!$projectroot)
  6865. {
  6866. $projectroot = $proj;
  6867. }
  6868. #
  6869. # special case for enlisting a project directly in the root
  6870. #
  6871. if ("\U$projectroot" eq "SDXROOT")
  6872. {
  6873. $usingroot = $main::TRUE;
  6874. $projectroot = ".";
  6875. }
  6876. #
  6877. # convert '/' to '\'
  6878. #
  6879. $projectroot =~ s/\//\\/g;
  6880. #
  6881. # push the map line onto the list so we can sort it
  6882. #
  6883. $mapline = sprintf("%s=%s", $proj, $projectroot);
  6884. push @main::DefaultMap, $mapline;
  6885. }
  6886. $appending and do
  6887. {
  6888. my @sorted = sort @main::DefaultMap;
  6889. for $line (@sorted)
  6890. {
  6891. @fields = split(/=/, $line);
  6892. printf $sdmap "%21s = %-52s\n", $fields[0], $fields[1];
  6893. }
  6894. };
  6895. $main::V1 and do
  6896. {
  6897. print "\n\ndefault map:\n\t";
  6898. for $line (@main::DefaultMap)
  6899. {
  6900. print "$line";
  6901. }
  6902. };
  6903. }
  6904. # _____________________________________________________________________________
  6905. #
  6906. # GetMapProjects
  6907. #
  6908. # Parameters:
  6909. #
  6910. # Output:
  6911. # returns 1 if map found and list created, 0 otherwise
  6912. # _____________________________________________________________________________
  6913. sub GetMapProjects
  6914. {
  6915. my $op = $_[0];
  6916. my $line = "";
  6917. @main::ExistingMap = ();
  6918. #
  6919. # read the map again since it may be changing
  6920. #
  6921. if (SDX::ReadSDMap($op, $main::Null))
  6922. {
  6923. for $p (@main::SDMapProjects)
  6924. {
  6925. $line = @$p[0] . "=" . @$p[1];
  6926. push @main::ExistingMap, $line;
  6927. }
  6928. }
  6929. $main::V3 and do
  6930. {
  6931. print "\nexisting map:\n\t";
  6932. for $line (@main::ExistingMap)
  6933. {
  6934. print "getmapproj: line = '$line'\n";
  6935. }
  6936. };
  6937. @main::ExistingMap and return 1;
  6938. return 0;
  6939. }
  6940. # _____________________________________________________________________________
  6941. #
  6942. # UpdateSDINIs
  6943. #
  6944. # If enlisting or repairing, creates an SD.INI in the root of each project which
  6945. # points SDPORT to the server:port for that project and sets SDCLIENT.
  6946. #
  6947. # If defecting,
  6948. #
  6949. # Parameters:
  6950. #
  6951. # Output:
  6952. # _____________________________________________________________________________
  6953. sub UpdateSDINIs
  6954. {
  6955. my $enlisting = ($_[0] eq "enlist");
  6956. my $defecting = ($_[0] eq "defect");
  6957. my $repairing = ($_[0] eq "repair");
  6958. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in UpdateSDINIs().\n");
  6959. ($enlisting || $repairing) and do
  6960. {
  6961. print "Writing SD.INIs in project roots";
  6962. foreach $project (@main::ProjectsInThisDepot)
  6963. {
  6964. print ".";
  6965. $usingroot = $main::FALSE;
  6966. $proj = @$project[$main::CBMProjectField];
  6967. $serverport = @$project[$main::CBMServerPortField];
  6968. $projectroot = @$project[$main::CBMProjectRootField];
  6969. #
  6970. # if no project root was given in the codebase map,
  6971. # assume the root is same as the project name
  6972. #
  6973. if (!$projectroot)
  6974. {
  6975. $projectroot = $proj;
  6976. }
  6977. #
  6978. # special case for enlisting a project directly in the root
  6979. #
  6980. if ("\U$projectroot" eq "SDXROOT")
  6981. {
  6982. $usingroot = $main::TRUE;
  6983. $projectroot = ".";
  6984. }
  6985. #
  6986. # convert '/' to '\'
  6987. #
  6988. $projectroot =~ s/\//\\/g;
  6989. #
  6990. # write the corresponding SD.INI
  6991. #
  6992. SDX::WriteSDINI($projectroot, $serverport);
  6993. }
  6994. };
  6995. $defecting and do
  6996. {
  6997. #
  6998. # sync #none the project and remove the whole thing
  6999. #
  7000. # can't just do sync #none across whole depot, since it would
  7001. # remove TOOLS dir and/or other default projects we want the user to keep
  7002. #
  7003. printf "\nDefecting client %s from projects in depot %s.\n", $main::SDClient, $serverport;
  7004. print "Please wait, syncing to remove files.";
  7005. foreach $project (@main::ProjectsInThisDepot)
  7006. {
  7007. $proj = @$project[$main::CBMProjectField];
  7008. $serverport = @$project[$main::CBMServerPortField];
  7009. $projectroot = @$project[$main::CBMProjectRootField];
  7010. #
  7011. # if no project root was given in the codebase map,
  7012. # assume the root is same as the project name
  7013. #
  7014. if (!$projectroot)
  7015. {
  7016. $projectroot = $proj;
  7017. }
  7018. #
  7019. # special case for enlisting a project directly in the root
  7020. #
  7021. if ("\U$projectroot" eq "SDXROOT")
  7022. {
  7023. $projectroot = ".";
  7024. }
  7025. #
  7026. # convert '/' to '\'
  7027. #
  7028. $projectroot =~ s/\//\\/g;
  7029. #
  7030. # maybe ghost files and remove the project
  7031. #
  7032. # specifically ignore the Tools project, it will be handled
  7033. # in FinishDefect()
  7034. #
  7035. $fullprojectroot = $main::SDXRoot . "\\" . $projectroot;
  7036. if (-e $fullprojectroot)
  7037. {
  7038. #
  7039. # sync #none to remove files
  7040. #
  7041. SDX::SyncFiles("defect", $fullprojectroot, $proj);
  7042. #
  7043. # nuke it all
  7044. #
  7045. SDX::RemoveProject($fullprojectroot, $serverport, $proj);
  7046. }
  7047. }
  7048. print "\n";
  7049. };
  7050. !$defecting and print "\nok.\n";
  7051. }
  7052. # _____________________________________________________________________________
  7053. #
  7054. # WriteSDINI
  7055. #
  7056. # Parameters:
  7057. #
  7058. # Output:
  7059. # _____________________________________________________________________________
  7060. sub WriteSDINI
  7061. {
  7062. $projectroot = $_[0];
  7063. $serverport = $_[1];
  7064. #
  7065. # write the corresponding SD.INI and make it RO, hidden
  7066. #
  7067. $fullprojectroot = $main::SDXRoot . "\\" . $projectroot;
  7068. $sdini = $fullprojectroot . "\\sd.ini";
  7069. system "mkdir $fullprojectroot >nul 2>&1";
  7070. -e $fullprojectroot or die "\nCan't create project root dir $fullprojectroot.\n";
  7071. #
  7072. # make it fully writable
  7073. #
  7074. system "attrib -R -H -S $sdini >nul 2>&1";
  7075. #
  7076. # write it
  7077. #
  7078. open(SDINI, ">$sdini") or die("\nCan't open $sdini for writing.\n");
  7079. printf SDINI "#\n# autogenerated by SDX - do not edit\n#\n";
  7080. printf SDINI "SDPORT=$serverport\n";
  7081. printf SDINI "SDCLIENT=$main::SDClient\n";
  7082. close(SDINI);
  7083. #
  7084. # make it read-only, hidden
  7085. #
  7086. system "attrib +R +H $sdini >nul 2>&1";
  7087. }
  7088. # _____________________________________________________________________________
  7089. #
  7090. # SyncFiles
  7091. #
  7092. # Parameters:
  7093. #
  7094. # Output:
  7095. # _____________________________________________________________________________
  7096. sub SyncFiles
  7097. {
  7098. my $enlisting = ($_[0] eq "enlist");
  7099. my $defecting = ($_[0] eq "defect");
  7100. my $repairing = ($_[0] eq "repair");
  7101. my $fullprojectroot = $_[1];
  7102. my $proj = $_[2];
  7103. my $root = ($proj eq "root");
  7104. my $filespec;
  7105. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in SyncFiles().\n");
  7106. $defecting and do
  7107. {
  7108. chdir $fullprojectroot or die("\nCan't chdir to $fullprojectroot.\n");
  7109. print ".";
  7110. #
  7111. # handle the root carefully
  7112. #
  7113. if ($root)
  7114. {
  7115. #
  7116. # sync files directly in the root
  7117. #
  7118. $filespec = "*";
  7119. system "sd.exe sync $filespec#none >nul 2>&1";
  7120. #
  7121. # get the list of root subdirs
  7122. #
  7123. @main::RemovableRootDirs = SDX::GetImmediateSubDirs($proj);
  7124. #
  7125. # sync in the subdirs of the root individually, except
  7126. # for the tools dir
  7127. #
  7128. foreach $dir (@main::RemovableRootDirs)
  7129. {
  7130. $cmd = "sd.exe sync $dir\\...#none 2>&1";
  7131. SDX::ShowSyncProgress($cmd, 20);
  7132. }
  7133. }
  7134. else
  7135. {
  7136. #
  7137. # only sync if we're not in the tools project
  7138. #
  7139. if ($proj ne $main::ToolsProject)
  7140. {
  7141. $filespec = "...";
  7142. $cmd = "sd.exe sync $filespec#none 2>&1";
  7143. SDX::ShowSyncProgress($cmd, 20);
  7144. }
  7145. }
  7146. chdir $main::StartDir or die("\nCan't cd to start dir $main::StartDir.\n");
  7147. };
  7148. ($enlisting || $repairing) and do
  7149. {
  7150. my @depotlist = ();
  7151. $enlisting and @depotlist = @main::EnlistDepots;
  7152. $defecting and @depotlist = @main::DefectDepots;
  7153. $repairing and @depotlist = @main::RepairDepots;
  7154. foreach $depot (@depotlist)
  7155. {
  7156. $serverport = @$depot[0];
  7157. printf "\n\nSyncing files in depot %s.", $serverport;
  7158. $cmd = "sd.exe -p $serverport -c $main::SDClient sync";
  7159. SDX::ShowSyncProgress($cmd, 20);
  7160. }
  7161. print "\n\n";
  7162. };
  7163. }
  7164. # _____________________________________________________________________________
  7165. #
  7166. # RemoveProject
  7167. #
  7168. # Parameters:
  7169. #
  7170. # Output:
  7171. # _____________________________________________________________________________
  7172. sub RemoveProject
  7173. {
  7174. my $fullprojectroot = $_[0];
  7175. my $serverport = $_[1];
  7176. my $proj = $_[2];
  7177. my $root = ($proj eq "root");
  7178. my $sdini = $fullprojectroot . "\\sd.ini";
  7179. print ".";
  7180. chdir $fullprojectroot or die("\nCan't cd to $fullprojectroot.\n");
  7181. #
  7182. # maybe remove everything in the project
  7183. #
  7184. $main::DefectWithPrejudice and do
  7185. {
  7186. #
  7187. # if we're in the root project, don't just blindly delnode
  7188. # figure out which dirs exist under the root and delete each of these,
  7189. # excluding the Tools dir
  7190. #
  7191. if ($root)
  7192. {
  7193. #
  7194. # delete only the subdirs of the root project, except
  7195. # for the tools dir
  7196. #
  7197. foreach $dir (@main::RemovableRootDirs)
  7198. {
  7199. my $path = $main::SDXRoot . "\\" . $dir;
  7200. (-e $path) and do
  7201. {
  7202. chdir $path or die("\nCan't cd to root subdir $path.\n");
  7203. system "del /F /S /Q /A:RHS *.* >nul 2>&1";
  7204. chdir $main::StartDir or die("\nCan't cd to start dir $main::StartDir.\n");
  7205. print ".";
  7206. system "rd /S /Q $path >nul 2>&1";
  7207. }
  7208. }
  7209. }
  7210. else
  7211. {
  7212. #
  7213. # only remove the project if it isn't the tools
  7214. #
  7215. if ($proj ne $main::ToolsProject)
  7216. {
  7217. system "del /F /S /Q /A:RHS *.* >nul 2>&1";
  7218. chdir $main::StartDir or die("\nCan't cd to start dir $main::StartDir.\n");
  7219. print ".";
  7220. system "rd /S /Q $fullprojectroot >nul 2>&1";
  7221. }
  7222. }
  7223. };
  7224. #
  7225. # lastly, remove SD.INI
  7226. #
  7227. system "attrib -R -H -S $sdini >nul 2>&1";
  7228. unlink $sdini;
  7229. }
  7230. # _____________________________________________________________________________
  7231. #
  7232. # GetImmediateSubDirs
  7233. #
  7234. # Ask SD for the list of dirs directly below $proj
  7235. #
  7236. # Parameters:
  7237. #
  7238. # Output:
  7239. # returns a list of subdirs
  7240. # _____________________________________________________________________________
  7241. sub GetImmediateSubDirs
  7242. {
  7243. my $proj = $_[0];
  7244. my @list = ();
  7245. my @lines = ();
  7246. my $proj2 = "";
  7247. @lines = `sd.exe dirs //depot/$main::Branch/$proj/* 2>&1`;
  7248. foreach $line (@lines)
  7249. {
  7250. if ($line =~ /no such file/)
  7251. {
  7252. @list = ();
  7253. last;
  7254. }
  7255. @fields = split(/\//,$line);
  7256. $proj2 = "\L@fields[$#fields]";
  7257. chop $proj2;
  7258. if ($main::ToolsInRoot)
  7259. {
  7260. ($proj2 ne $main::ToolsPath) and push @list, $proj2;
  7261. }
  7262. else
  7263. {
  7264. ($proj2 ne $main::ToolsProject) and push @list, $proj2;
  7265. }
  7266. }
  7267. $main::V2 and do
  7268. {
  7269. print "\n\n\ngetimmediatesubdirs: list = '@list'\n\n\n";
  7270. };
  7271. return @list;
  7272. }
  7273. # _____________________________________________________________________________
  7274. #
  7275. # ToolsEtc
  7276. #
  7277. # Puts the SD/SDX tools, batch files and aliases into the enlistment
  7278. #
  7279. # Parameters:
  7280. #
  7281. # Output:
  7282. # _____________________________________________________________________________
  7283. sub ToolsEtc
  7284. {
  7285. my $op = $_[0];
  7286. my $enlisting = ($op eq "enlist");
  7287. my $defecting = ($op eq "defect");
  7288. my $repairing = ($op eq "repair");
  7289. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in ToolsEtc().\n");
  7290. #
  7291. # if the codebase map gave us a tools project, go there and sync for the
  7292. # user, otherwise handle the tools manually
  7293. #
  7294. if ($main::ToolsProject)
  7295. {
  7296. SDX::SyncTools($op);
  7297. }
  7298. else
  7299. {
  7300. SDX::CopyTools($op);
  7301. }
  7302. #
  7303. # write or remove the script to set the SD env vars
  7304. #
  7305. SDX::WriteSDINIT($op);
  7306. #
  7307. # write or remove project navigation aliases from $main::SDMap
  7308. #
  7309. SDX::WriteAliases($op);
  7310. #
  7311. # maybe clean up files in the root
  7312. #
  7313. $defecting and $main::DefectWithPrejudice and do
  7314. {
  7315. chdir $main::SDXRoot or die("\nCan't cd to $main::SDXRoot.\n");
  7316. system "del /Q /A:-R *.* >nul 2>&1";
  7317. chdir $main::StartDir or die("\nCan't cd to start dir $main::StartDir.\n");
  7318. };
  7319. }
  7320. # _____________________________________________________________________________
  7321. #
  7322. # SyncTools
  7323. #
  7324. # Parameters:
  7325. #
  7326. # Output:
  7327. #
  7328. # _____________________________________________________________________________
  7329. sub SyncTools
  7330. {
  7331. my $op = $_[0];
  7332. my $enlisting = ($op eq "enlist");
  7333. my $defecting = ($op eq "defect");
  7334. my $repairing = ($op eq "repair");
  7335. my $n = 0;
  7336. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in SyncTools().\n");
  7337. (($enlisting and $main::NewEnlist) || ($repairing and $main::Sync)) and do
  7338. {
  7339. print "\n\nPlease wait, syncing tools $main::ToolsProjectPath.";
  7340. !(-e $main::ToolsProjectPath) and system "mkdir $main::ToolsProjectPath >nul 2>&1";
  7341. chdir $main::ToolsProjectPath;
  7342. $cmd = "sd.exe sync -f $main::ToolsProjectPath\\... 2>&1";
  7343. SDX::ShowSyncProgress($cmd, 10);
  7344. #
  7345. # make sure the SD client and PERL runtimes are read-only, since SD will leave them writable
  7346. # during the sync and susceptible to a clean build cleansing with del /s
  7347. #
  7348. system "attrib +R $main::ToolsProjectPath\\$main::Platform\\perl* >nul 2>&1";
  7349. system "attrib +R $main::ToolsProjectPath\\$main::Platform\\sd.exe >nul 2>&1";
  7350. };
  7351. }
  7352. # _____________________________________________________________________________
  7353. #
  7354. # CopyTools
  7355. #
  7356. # Parameters:
  7357. #
  7358. # Output:
  7359. # _____________________________________________________________________________
  7360. sub CopyTools
  7361. {
  7362. my $enlisting = ($_[0] eq "enlist");
  7363. my $defecting = ($_[0] eq "defect");
  7364. my $repairing = ($_[0] eq "repair");
  7365. my $tools = "sdtools";
  7366. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in CopyTools().\n");
  7367. #
  7368. # when defecting, be selective about which files we remove since most are
  7369. # in use
  7370. #
  7371. ($enlisting || $repairing) and do
  7372. {
  7373. #
  7374. # if we know the codebase map, add it to the list of things
  7375. # to copy to the tools dir
  7376. #
  7377. $main::CodeBaseMapFile and push @{$main::SDXTools{toSDTools}}, $main::CodeBaseMapFile;
  7378. #
  7379. # create the local tools dir
  7380. #
  7381. $destroot = "$main::SDXRoot\\$tools";
  7382. system "mkdir $destroot >nul 2>&1";
  7383. -e $destroot or die("\nCan't create tools dir $destroot.\n");
  7384. print "\n\nCopying Source Depot tools to $destroot";
  7385. };
  7386. foreach $file (@{$main::SDXTools{toSDXRoot}})
  7387. {
  7388. $src = "$main::StartPath\\$file";
  7389. $dest = "$main::SDXRoot\\$file";
  7390. ($enlisting || $repairing) and print "." and SDX::CopyFile($src, $dest);
  7391. $defecting and unlink $dest;
  7392. }
  7393. ($enlisting || $repairing) and do
  7394. {
  7395. foreach $file (@{$main::SDXTools{toSDTools}})
  7396. {
  7397. print ".";
  7398. $src = "$main::StartPath\\$file";
  7399. $dest = "$main::SDXRoot\\$tools\\$file";
  7400. SDX::CopyFile($src, $dest);
  7401. }
  7402. foreach $file (@{$main::SDXTools{toSDToolsPA}})
  7403. {
  7404. print ".";
  7405. $src = "$main::StartPath\\$main::Platform\\$file";
  7406. $dest = "$main::SDXRoot\\$tools\\$file";
  7407. SDX::CopyFile($src, $dest);
  7408. }
  7409. print "\nok.\n";
  7410. };
  7411. }
  7412. # _____________________________________________________________________________
  7413. #
  7414. # CopyFile
  7415. #
  7416. # Parameters:
  7417. #
  7418. # Output:
  7419. # _____________________________________________________________________________
  7420. sub CopyFile
  7421. {
  7422. $#_ == 1 or die("\nNot enough arguments to CopyFile().\n");
  7423. $src = $_[0];
  7424. $dest = $_[1];
  7425. $main::V2 and do
  7426. {
  7427. printf "\ncopy /Y /V $src $dest\n";
  7428. };
  7429. system "copy /Y /V $src $dest >nul 2>&1";
  7430. -e $dest or die("\nCan't copy $src to enlistment root $dest.\n");
  7431. }
  7432. # _____________________________________________________________________________
  7433. #
  7434. # WriteSDINIT
  7435. #
  7436. # Write the SD environment variables to a batch file for the user to run later.
  7437. #
  7438. # Parameters:
  7439. #
  7440. # Output:
  7441. # _____________________________________________________________________________
  7442. sub WriteSDINIT
  7443. {
  7444. my $enlisting = ($_[0] eq "enlist");
  7445. my $defecting = ($_[0] eq "defect");
  7446. my $repairing = ($_[0] eq "repair");
  7447. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in WriteSDINIT().\n");
  7448. #
  7449. # SDINIT.CMD goes in the tools dir if we have one
  7450. # otherwise to SDXROOT
  7451. #
  7452. $file = "\\sdinit.cmd";
  7453. if ($main::ToolsProject)
  7454. {
  7455. $main::SDINIT = $main::ToolsProjectPath . $file;
  7456. }
  7457. else
  7458. {
  7459. $main::SDINIT = $main::SDXRoot . $file;
  7460. }
  7461. #
  7462. # make it writable
  7463. #
  7464. system "attrib -R -H -S $main::SDINIT >nul 2>&1";
  7465. #
  7466. # maybe (re)write
  7467. #
  7468. (($enlisting and !(-e $main::SDINIT)) or $repairing) and do
  7469. {
  7470. open(SDINIT, ">$main::SDINIT") or die("\nCan't open $main::SDINIT for writing.\n");
  7471. printf SDINIT "\@if \"%%_ECHO%%\" == \"\" \@echo off\n\n";
  7472. printf SDINIT "rem\nrem SDINIT.CMD -- autogenerated by SDX\nrem\n\n";
  7473. printf SDINIT "set SDXROOT=%s\n", $main::SDXRoot;
  7474. printf SDINIT "set SDCONFIG=sd.ini\n";
  7475. printf SDINIT "if \"%%SDEDITOR%%\" == \"\" set SDEDITOR=notepad.exe\n";
  7476. printf SDINIT "if \"%%SDDIFF%%\" == \"\" set SDDIFF=windiff.exe\n\n";
  7477. #
  7478. # only change the user's path if there's no tools dir
  7479. #
  7480. !$main::ToolsProject and printf SDINIT "set PATH=\%SDXROOT\%\\sdtools;\%PATH\%\n\n";
  7481. if ($main::ToolsProject)
  7482. {
  7483. my $tools;
  7484. $tools = $main::ToolsProject . "\\" . $main::ToolsPath;
  7485. $main::ToolsInRoot and $tools = $main::ToolsPath;
  7486. printf SDINIT "if exist \%SDXROOT\%\\$tools\\%PROCESSOR_ARCHITECTURE\%\\alias.exe \%SDXROOT\%\\$tools\\%PROCESSOR_ARCHITECTURE\%\\alias -f \%SDXROOT\%\\%s\\alias.sdx -f \%SDXROOT\%\\%s\\alias.%s\n\n", $tools, $tools, $main::CodeBase;
  7487. printf SDINIT "if exist \%SDXROOT\%\\%s\sdvars.cmd call \%SDXROOT\%\\%s\sdvars.cmd\n", $tools, $tools;
  7488. }
  7489. else
  7490. {
  7491. printf SDINIT "alias -f \%SDXROOT\%\\alias.sdx -f \%SDXROOT\%\\alias.%s\n\n", $main::CodeBase;
  7492. printf SDINIT "if exist \%SDXROOT\%\\sdvars.cmd call \%SDXROOT\%\\sdvars.cmd\n";
  7493. }
  7494. close(SDINIT);
  7495. #
  7496. # make it read-only
  7497. #
  7498. system "attrib +R $main::SDINIT >nul 2>&1";
  7499. };
  7500. #
  7501. # maybe delete it
  7502. #
  7503. $defecting and unlink $main::SDINIT;
  7504. }
  7505. # _____________________________________________________________________________
  7506. #
  7507. # WriteAliases
  7508. #
  7509. # Write ALIAS.<codebase> with project-specific aliases for CD'g around the tree
  7510. #
  7511. # Parameters:
  7512. #
  7513. # Output:
  7514. # _____________________________________________________________________________
  7515. sub WriteAliases
  7516. {
  7517. my $op = $_[0];
  7518. my $enlisting = ($op eq "enlist");
  7519. my $defecting = ($op eq "defect");
  7520. my $repairing = ($op eq "repair");
  7521. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in WriteAliases().\n");
  7522. #
  7523. # ALIAS.<codebase> goes in the tools dir if we have one
  7524. # otherwise to SDXROOT
  7525. #
  7526. $file = "\\alias.";
  7527. if ($main::ToolsProject)
  7528. {
  7529. $main::ALIASES = $main::ToolsProjectPath . $file . $main::CodeBase;
  7530. }
  7531. else
  7532. {
  7533. $main::ALIASES = $main::SDXRoot . $file . $main::CodeBase;
  7534. }
  7535. #
  7536. # make it writable
  7537. #
  7538. system "attrib -R -H -S $main::ALIASES >nul 2>&1";
  7539. #
  7540. # maybe (re)write it
  7541. #
  7542. ($enlisting || $repairing) and do
  7543. {
  7544. #
  7545. # get the list of projects and roots
  7546. # need to reread the map since it may have changed
  7547. #
  7548. if (SDX::ReadSDMap($op, $main::Null))
  7549. {
  7550. open(ALIASES, ">$main::ALIASES") or die("\nCan't open $main::ALIASES for writing.\n");
  7551. print ALIASES "\n#\n# autogenerated by SDX -- do not edit\n";
  7552. print ALIASES "#\n";
  7553. #
  7554. # for each project and root, write an alias
  7555. #
  7556. foreach $projectandroot (@main::SDMapProjects)
  7557. {
  7558. $project = @$projectandroot[0];
  7559. $project =~ tr/A-Z/a-z/;
  7560. if (!exists($main::BadAliases{$project}))
  7561. {
  7562. printf ALIASES "%-24scd /d \%SDXROOT\%\\%s\\\$1\n", @$projectandroot[0], @$projectandroot[1];
  7563. }
  7564. }
  7565. close(ALIASES);
  7566. #
  7567. # make it read-only
  7568. #
  7569. system "attrib +R $main::ALIASES >nul 2>&1";
  7570. }
  7571. };
  7572. $defecting and do
  7573. {
  7574. unlink $main::ALIASES;
  7575. };
  7576. }
  7577. # _____________________________________________________________________________
  7578. #
  7579. # FilesOpen
  7580. #
  7581. # Parameters:
  7582. # $serverport
  7583. #
  7584. # Output:
  7585. # returns TRUE if the client has files opened in any of the depots, FALSE
  7586. # otherwise
  7587. # _____________________________________________________________________________
  7588. sub FilesOpen
  7589. {
  7590. my $depot;
  7591. my @open = ();
  7592. print "\nChecking for open files.";
  7593. #
  7594. # look for open files in each depot
  7595. #
  7596. foreach $depot (@main::DefectDepots)
  7597. {
  7598. print ".";
  7599. my $serverport = @$depot[0];
  7600. push @open, `sd.exe -p $serverport -c $main::SDClient opened 2>&1`;
  7601. }
  7602. my @err = ();
  7603. (@err = grep(/failed/, @open)) and do
  7604. {
  7605. print "\n\nOne or more depots are unavailable:\n\n@err\n";
  7606. die("\n");
  7607. };
  7608. $main::V3 and print "open = '@open'\n";
  7609. (@open = grep(/\/\//, @open)) and print "\nok.\n";
  7610. #
  7611. # if this list has anything in it, open files were found
  7612. #
  7613. @open;
  7614. }
  7615. # _____________________________________________________________________________
  7616. #
  7617. # GetCodeBases
  7618. #
  7619. # Parameters:
  7620. #
  7621. # Output:
  7622. #
  7623. # _____________________________________________________________________________
  7624. sub GetCodeBases
  7625. {
  7626. $rc = system "dir /B $main::StartPath\\projects.* > $main::tmptmp 2>nul";
  7627. if ($rc / 256)
  7628. {
  7629. print "\t\t(none)\n";
  7630. }
  7631. else
  7632. {
  7633. open(CBLIST, "<$main::tmptmp") or die("\nCan't open $main::tmptmp for reading.\n");
  7634. while ($line = <CBLIST>)
  7635. {
  7636. #
  7637. # trim out noise
  7638. #
  7639. chop $line;
  7640. $line =~ tr/a-z/A-Z/;
  7641. $line =~ s/PROJECTS|CMD|INC|BAT|//g;
  7642. $line =~ s/^\.//g;
  7643. if ($line)
  7644. {
  7645. printf "\t\t %s\n", $line;
  7646. }
  7647. }
  7648. close(CBLIST);
  7649. }
  7650. }
  7651. # _____________________________________________________________________________
  7652. #
  7653. # VerifyCBMap
  7654. #
  7655. # Parameters:
  7656. #
  7657. # Output:
  7658. #
  7659. # _____________________________________________________________________________
  7660. sub VerifyCBMap
  7661. {
  7662. my $codebase = $_[0];
  7663. my $rc;
  7664. #
  7665. # make sure we have the codebase map file
  7666. #
  7667. $main::CodeBaseMapFile = "projects." . $codebase;
  7668. $main::CodeBaseMap = $main::StartPath . "\\" . $main::CodeBaseMapFile;
  7669. $main::V3 and do
  7670. {
  7671. print "\nverifycbmap: codebase = '$codebase'\n";
  7672. print "verifycbmap: codebasemapfile = '$main::CodeBaseMapFile'\n";
  7673. print "verifycbmap: codebasemap = '$main::CodeBaseMap'\n";
  7674. };
  7675. return -e $main::CodeBaseMap;
  7676. }
  7677. # _____________________________________________________________________________
  7678. #
  7679. # SyncOtherDirs
  7680. #
  7681. # Parameters:
  7682. #
  7683. # Output:
  7684. #
  7685. # _____________________________________________________________________________
  7686. sub SyncOtherDirs
  7687. {
  7688. my $enlisting = ($_[0] eq "enlist");
  7689. my $defecting = ($_[0] eq "defect");
  7690. my $repairing = ($_[0] eq "repair");
  7691. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in SyncOtherDirs().\n");
  7692. (($enlisting and $main::NewEnlist) || $repairing) and do
  7693. {
  7694. foreach $path (@main::OtherDirs)
  7695. {
  7696. if ($path eq ".")
  7697. {
  7698. my $fullpath = $main::SDXRoot;
  7699. my $filespec = ($fullpath =~ /\\$/ ? "" : "\\") . "*";
  7700. $fullpath .= $filespec;
  7701. print "\n\nPlease wait, syncing $fullpath.";
  7702. chdir $fullpath;
  7703. print ".";
  7704. system "sd.exe sync -f $fullpath >nul 2>&1";
  7705. print ".\n\n";
  7706. }
  7707. else
  7708. {
  7709. my $fullpath = $main::SDXRoot . "\\" . $path;
  7710. print "\n\nSyncing $fullpath.";
  7711. chdir $fullpath;
  7712. print ".";
  7713. system "sd.exe sync -f $fullpath\\... >nul 2>&1";
  7714. print ".\n\n";
  7715. }
  7716. }
  7717. };
  7718. }
  7719. # _____________________________________________________________________________
  7720. #
  7721. # ReadProfile
  7722. #
  7723. # reads codebase, branch and list of projects from text file
  7724. #
  7725. # Parameters:
  7726. #
  7727. # Output:
  7728. # sets $main::ProfileCodeBase
  7729. # sets $main::ProfileBranch
  7730. # populates $main::ProfileProjects
  7731. # _____________________________________________________________________________
  7732. sub ReadProfile
  7733. {
  7734. if (-e $main::Profile)
  7735. {
  7736. open(PROFILE, "<$main::Profile") or die("\nCan't open profile $main::Profile for reading.\n");
  7737. while ($line = <PROFILE>)
  7738. {
  7739. #
  7740. # throw away comments
  7741. #
  7742. $line =~ /^#/ and next;
  7743. chop $line;
  7744. #
  7745. # get codebase name
  7746. #
  7747. if ($line =~ /^CODEBASE/)
  7748. {
  7749. @fields = split(/[\t\s]*=[\t\s]*/, $line);
  7750. $main::ProfileCodeBase = @fields[1];
  7751. $main::ProfileCodeBase =~ s/[\t\s]*//g;
  7752. }
  7753. #
  7754. # get branch to enlist
  7755. #
  7756. if ($line =~ /^BRANCH/)
  7757. {
  7758. @fields = split(/[\t\s]*=[\t\s]*/, $line);
  7759. $main::ProfileBranch = @fields[1];
  7760. $main::ProfileBranch =~ s/[\t\s]*//g;
  7761. }
  7762. #
  7763. # get any projects
  7764. #
  7765. if ($line =~ /^PROJECTS/)
  7766. {
  7767. $line =~ s/^PROJECTS[\t\s]*=[\t\s]*//g;
  7768. @main::ProfileProjects = split(/[\t\s]+/,$line);
  7769. }
  7770. }
  7771. close(PROFILE);
  7772. $main::V2 and do
  7773. {
  7774. print "\n";
  7775. printf "readprofile: codebase = '%s'\n", $main::ProfileCodeBase;
  7776. printf "readprofile: branch = '%s'\n\n", $main::ProfileBranch;
  7777. foreach $p (@main::ProfileProjects)
  7778. {
  7779. printf "readprofile: profileprojects = '%s'\n", $p;
  7780. }
  7781. };
  7782. #
  7783. # make sure we have everything
  7784. #
  7785. $main::ProfileCodeBase and $main::ProfileBranch and @main::ProfileProjects and return 1;
  7786. print "The profile\n\n\t$main::Profile\n\nis missing the ";
  7787. !$main::ProfileCodeBase and print "codebase name.\n" and return 0;
  7788. !$main::ProfileBranch and print "branch name.\n" and return 0;
  7789. !@main::ProfileProjects and print "project list.\n";
  7790. }
  7791. else
  7792. {
  7793. print "\nCan't find profile $main::Profile.\n";
  7794. }
  7795. return 0;
  7796. }
  7797. # _____________________________________________________________________________
  7798. #
  7799. # WriteDefaultSetEnv
  7800. #
  7801. # Parameters:
  7802. #
  7803. # Output:
  7804. # _____________________________________________________________________________
  7805. sub WriteDefaultSetEnv
  7806. {
  7807. return;
  7808. }
  7809. # _____________________________________________________________________________
  7810. #
  7811. # Backup
  7812. #
  7813. # Parameters:
  7814. #
  7815. # Output:
  7816. # _____________________________________________________________________________
  7817. sub Backup
  7818. {
  7819. return;
  7820. }
  7821. # _____________________________________________________________________________
  7822. #
  7823. # Restore
  7824. #
  7825. # Parameters:
  7826. #
  7827. # Output:
  7828. # _____________________________________________________________________________
  7829. sub Restore
  7830. {
  7831. return;
  7832. }
  7833. # _____________________________________________________________________________
  7834. #
  7835. # Type1Root
  7836. #
  7837. # Root: field for client view depends on codebase type
  7838. #
  7839. # for type 1 (1 project/depot), root includes project name
  7840. # for type 2 (N projects/depot), root is just main::SDXRoot
  7841. #
  7842. # Parameters:
  7843. #
  7844. # Output:
  7845. # $root
  7846. # _____________________________________________________________________________
  7847. sub Type1Root
  7848. {
  7849. my $root = $_[0];
  7850. my $project;
  7851. my $proj;
  7852. my $projroot;
  7853. #
  7854. # only one project per depot
  7855. #
  7856. $project = @main::ProjectsInThisDepot[0];
  7857. $proj = @$project[$main::CBMProjectField];
  7858. $projroot = @$project[$main::CBMProjectRootField];
  7859. #
  7860. # if no project root was given in the codebase map, assume
  7861. # the root is same as the project name
  7862. #
  7863. !$projroot and $projroot = $proj;
  7864. #
  7865. # if we're not the root project, append project name
  7866. #
  7867. !($projroot eq "sdxroot") and $root .= "\\$projroot";
  7868. return $root;
  7869. }
  7870. # _____________________________________________________________________________
  7871. #
  7872. # MakeUniqueClient
  7873. #
  7874. # Returns a client name unique in the depots if $main::SDClient already
  7875. # exists. Waits on a global mutex to guarantee name is unique.
  7876. #
  7877. # Parameters:
  7878. #
  7879. # Output:
  7880. # existing $main::SDClient if it's unique
  7881. # else a unique variation of $main::SDClient
  7882. # _____________________________________________________________________________
  7883. sub MakeUniqueClient
  7884. {
  7885. my $client = $main::SDClient;
  7886. my @list = ();
  7887. print "\nPlease wait, verifying client name $main::SDClient is available";
  7888. #
  7889. # we want to know we're the only enlist process trying to generate
  7890. # a unique client name
  7891. #
  7892. $main::V3 and print "\ncreating mutex\n";
  7893. $main::Mutex = Win32::Mutex->new($main::FALSE, "SDX_ENLIST");
  7894. #
  7895. # wait til we get it
  7896. #
  7897. $main::V3 and print "waiting on mutex\n";
  7898. $main::Mutex->wait(0x7fffffff);
  7899. $main::V3 and print "got it\n";
  7900. $main::HaveMutex = $main::TRUE;
  7901. #
  7902. # build a list of clients in each depot
  7903. #
  7904. # check for access denied as we go
  7905. #
  7906. foreach $depot (@main::VerifyDepots)
  7907. {
  7908. print ".";
  7909. $serverport = @$depot[0];
  7910. $main::V3 and print "$serverport\n";
  7911. push (@list, `sd.exe -p $serverport clients 2>&1`);
  7912. SDX::AccessDenied(\@list, $serverport) and die("\n");
  7913. }
  7914. $main::V4 and print "\n\nclient list = @list\n";
  7915. #
  7916. # loop til we have a unique name
  7917. #
  7918. $num = 1;
  7919. while (grep(/Client $client /i, @list))
  7920. {
  7921. print ".";
  7922. $client = "$main::SDClient-" . $num++;
  7923. }
  7924. #
  7925. # hang onto the mutex until we've registered the first client
  7926. # using the new name -- release it in Enlist()
  7927. #
  7928. $main::V3 and print "leaving MakeUniqueClient\n";
  7929. return $client;
  7930. }
  7931. # _____________________________________________________________________________
  7932. #
  7933. # VerifyCodeBaseAndBranch
  7934. #
  7935. #
  7936. # Parameters:
  7937. #
  7938. # Output:
  7939. # returns TRUE if error and usage needed, else FALSE
  7940. # _____________________________________________________________________________
  7941. sub VerifyCodeBaseAndBranch
  7942. {
  7943. my $codebase = $_[0];
  7944. my $branch = $_[1];
  7945. my $usage = $main::FALSE;
  7946. $main::V2 and print "codebase = '$codebase'\nbranch = '$branch'\n";
  7947. #
  7948. # verify
  7949. #
  7950. ($codebase eq "") and print "\nMissing codebase.\n" and $usage = $main::TRUE;
  7951. (substr($codebase,0,1) =~ /[\/-]/) and do
  7952. {
  7953. $codebase !~ /\?/ and print "\nCodebase name '$codebase' appears to be a command switch.\n";
  7954. $usage = $main::TRUE;
  7955. };
  7956. substr($codebase,0,1) =~ /@/ and print "\nCodebase name '$codebase' appears to be a client name.\n" and $usage = $main::TRUE;
  7957. ($branch eq "") and print "\nMissing branch.\n" and $usage = $main::TRUE;
  7958. (substr($branch,0,1) =~ /[\/-]/) and print "\nBranch name '$branch' appears to be a command switch.\n" and $usage = $main::TRUE;
  7959. return $usage;
  7960. }
  7961. # _____________________________________________________________________________
  7962. #
  7963. # AccessDenied
  7964. #
  7965. # Parameters:
  7966. # $list -- to grep for access error
  7967. # $serverport -- depot where access failed
  7968. #
  7969. # Output:
  7970. # error msg and return 1 if denied, else 0
  7971. # _____________________________________________________________________________
  7972. sub AccessDenied
  7973. {
  7974. my ($list) = $_[0];
  7975. my $serverport = $_[1];
  7976. $main::V3 and do
  7977. {
  7978. print "accessdenied: list = '@$list'\n";
  7979. print "accessdenied: serverport = '$serverport'\n";
  7980. };
  7981. grep(/ don't have permission /, @$list) and do
  7982. {
  7983. print "\n\n\nAccess denied to depot $serverport.\n";
  7984. print "\nYour domain user account must have permission to use this depot, or belong\n";
  7985. print "to a domain group that has access. Please email INFRA for assistance.\n";
  7986. return 1;
  7987. };
  7988. return 0;
  7989. }
  7990. # _____________________________________________________________________________
  7991. #
  7992. # ShowSyncProgress
  7993. #
  7994. # Parameters:
  7995. # $cmd -- sd sync cmd to run
  7996. #
  7997. # Output:
  7998. # ...
  7999. # _____________________________________________________________________________
  8000. sub ShowSyncProgress
  8001. {
  8002. my $cmd = $_[0];
  8003. my $mod = $_[1];
  8004. open FILE, "$cmd |" or die("\nShowSyncProgress: can't open pipe for $cmd.\n");
  8005. while (<FILE>) { !(++$n % $mod) and print "."; }
  8006. close FILE;
  8007. }
  8008. # _____________________________________________________________________________
  8009. #
  8010. # ShowSDProgress
  8011. #
  8012. # Parameters:
  8013. # $cmd -- sd cmd to run
  8014. #
  8015. # Output:
  8016. # ...
  8017. # _____________________________________________________________________________
  8018. sub ShowSDProgress
  8019. {
  8020. my $cmd = $_[0];
  8021. my $mod = $_[1];
  8022. open FILE, "$cmd |" or die("\nShowSDProgress: can't open pipe for $cmd.\n");
  8023. while (<FILE>) { !(++$n % $mod) and print "."; }
  8024. close FILE;
  8025. }
  8026. # _____________________________________________________________________________
  8027. #
  8028. # ServerPort
  8029. #
  8030. # for type 1 depots we're in a project root and will have an SD.INI
  8031. # to tell us server:port
  8032. # for type 2 depots rely on passed in $sp
  8033. #
  8034. # Parameters:
  8035. #
  8036. # cmd or codebase type
  8037. #
  8038. # Output:
  8039. # ...
  8040. # _____________________________________________________________________________
  8041. sub ServerPort
  8042. {
  8043. my $type = $_[0];
  8044. my $sp = $_[1];
  8045. return ($type == 2 ? "-p $sp" : "");
  8046. }
  8047. # _____________________________________________________________________________
  8048. #
  8049. # GetPublicChangeNum
  8050. #
  8051. # get the public change number from $main::SDXROOT\public\public_changenum.sd
  8052. # if there is one
  8053. #
  8054. # Parameters:
  8055. #
  8056. # Output:
  8057. # set $main::PublicChangeNum
  8058. # _____________________________________________________________________________
  8059. sub GetPublicChangeNum
  8060. {
  8061. ("\U$main::CodeBase" eq "NT") and do
  8062. {
  8063. my $pcn = "$main::SDXRoot\\public\\public_changenum.sd";
  8064. my $line = "";
  8065. if (open(FILE, "<$pcn"))
  8066. {
  8067. $line = <FILE>;
  8068. close(FILE);
  8069. #
  8070. # $line is of the form "Change XXXX created."
  8071. #
  8072. return (split(/ /, $line))[1];
  8073. }
  8074. };
  8075. return 0;
  8076. }
  8077. # _____________________________________________________________________________
  8078. #
  8079. # GetDepotTypes
  8080. #
  8081. # called by OtherOp only when executing type 2 commands
  8082. #
  8083. # Parameters:
  8084. #
  8085. # Output:
  8086. # populate %main::DepotType
  8087. # _____________________________________________________________________________
  8088. sub GetDepotTypes
  8089. {
  8090. #
  8091. # for type 2 commands read the codebase map
  8092. # and figure out the depot type
  8093. #
  8094. if (SDX::VerifyCBMap($main::CodeBase))
  8095. {
  8096. SDX::ReadCodeBaseMap();
  8097. SDX::MakePGDLists();
  8098. }
  8099. else
  8100. {
  8101. print "\n\nError: Can't find codebase map $main::CodeBaseMap.\n";
  8102. die("\nContact the SDX alias.\n");
  8103. }
  8104. }
  8105. # _____________________________________________________________________________
  8106. #
  8107. # MakeProjectRoot
  8108. #
  8109. # for type 1 projects (1 project/depot), the project name is
  8110. # included in the Root: field of the client view and must not
  8111. # be used in the RHS of the view line
  8112. #
  8113. # for type 2 projects (N projects/depot) the project can't be part
  8114. # of the root and so must be included in the RHS
  8115. #
  8116. # Parameters:
  8117. #
  8118. # Output:
  8119. # returns
  8120. # _____________________________________________________________________________
  8121. sub MakeProjectRoot
  8122. {
  8123. my $proj = $_[0];
  8124. my $projroot = $_[1];
  8125. $main::V3 and do
  8126. {
  8127. print "makeprojectroot: proj = '$proj'\n";
  8128. print "makeprojectroot: projroot = '$projroot'\n";
  8129. print "makeprojectroot: projtype{$proj} = $main::ProjectType{$proj}\n";
  8130. };
  8131. my $pr = ($main::ProjectType{$proj} == 2 ) ? "/$projroot" : "";
  8132. $main::V3 and print "makeprojectroot: returning '$pr'\n";
  8133. return $pr;
  8134. }
  8135. # _____________________________________________________________________________
  8136. #
  8137. # DepotErrors
  8138. #
  8139. # format and print the number of errors we got trying to talk to depot
  8140. #
  8141. # Parameters:
  8142. #
  8143. # Output:
  8144. # _____________________________________________________________________________
  8145. sub DepotErrors
  8146. {
  8147. my ($counters) = $_[0];
  8148. my $pad = $_[1];
  8149. my $errors = $_[2];
  8150. push @$counters, sprintf "\nSD CLIENT ERRORS:%s%s\n", $pad, $errors;
  8151. };
  8152. # _____________________________________________________________________________
  8153. #
  8154. # Changes
  8155. #
  8156. # generate build changelist summary for Main and lab branch(es)
  8157. # process all other sdx changes commands normally
  8158. #
  8159. # Parameters:
  8160. #
  8161. # Output:
  8162. # _____________________________________________________________________________
  8163. sub Changes
  8164. {
  8165. $main::V3 and do
  8166. {
  8167. print "buildnum = $main::BuildNumber\n";
  8168. print "minusb = $main::MinusB\n";
  8169. print "sdcmd = $main::SDCmd\n";
  8170. print "userargs = $main::UserArgs\n";
  8171. };
  8172. #
  8173. # if not looking for build change summary, handle sdx changes command
  8174. # normally
  8175. #
  8176. if (!$main::MinusB)
  8177. {
  8178. SDX::OtherOp($main::SDCmd, $main::UserArgs);
  8179. }
  8180. else
  8181. {
  8182. #
  8183. # return if not NT
  8184. #
  8185. ($main::CodeBase ne "NT") and do
  8186. {
  8187. print "\nsdx changes -b only supported for NT codebase.\n";
  8188. return;
  8189. };
  8190. #
  8191. # create hash of history
  8192. #
  8193. (!SDX::GetBuildHistory($main::BuildNumber)) and return;
  8194. (!$main::BuildHistory{$main::BuildNumber}{buildtype}) and do
  8195. {
  8196. print "\nCould not determine $main::BuildNumber build type from RI/integration change comments.\n";
  8197. return;
  8198. };
  8199. #
  8200. # generate the lists of changes in this build
  8201. #
  8202. $type = $main::BuildHistory{$main::BuildNumber}{buildtype};
  8203. #
  8204. # Main
  8205. #
  8206. # consists of changes from lab branch(es) and Main
  8207. #
  8208. # sdx changes -b 2271 produces
  8209. # changes.2271.main.txt
  8210. # changes.2271.lab02_n.txt
  8211. # changes.2271.lab03_n.txt
  8212. # changes.2271.lab07_n.txt
  8213. #
  8214. ($type eq "MAIN") and do
  8215. {
  8216. $main::V2 and do
  8217. {
  8218. print "\n$main::BuildNumber is an RI:\n";
  8219. SDX::PrintBH(\%main::BuildHistory, $main::BuildNumber);
  8220. };
  8221. SDX::GetMainChanges($main::BuildNumber, $type);
  8222. };
  8223. #
  8224. # BETA
  8225. #
  8226. # consists of changes from the beta branch
  8227. #
  8228. # sdx changes -b 2277 produces
  8229. # changes.2277.beta1.txt
  8230. #
  8231. ($type eq "BETA") and do
  8232. {
  8233. $main::V2 and do
  8234. {
  8235. print "\n$main::BuildNumber is a BETA:\n";
  8236. SDX::PrintBH(\%main::BuildHistory, $main::BuildNumber);
  8237. };
  8238. #
  8239. # for beta builds there's only one contributing branch, betaX
  8240. # use the first one in the list
  8241. #
  8242. my $branch = @{$main::BuildHistory{$main::BuildNumber}{branches}}[0];
  8243. SDX::GetBranchChanges($main::BuildNumber, $branch, $type);
  8244. };
  8245. #
  8246. # IDX
  8247. #
  8248. # consists of changes from the original RI build and the IDX branch
  8249. #
  8250. # sdx changes -b 2267 produces
  8251. # changes.2267.main.txt
  8252. # changes.2267.lab02_n.txt
  8253. # changes.2267.idx01.txt
  8254. #
  8255. ($type eq "IDX") and do
  8256. {
  8257. $main::V2 and do
  8258. {
  8259. print "\n$main::BuildNumber is an IDX:\n";
  8260. SDX::PrintBH(\%main::BuildHistory, $main::BuildNumber);
  8261. };
  8262. #
  8263. # get changes from the original RI build
  8264. #
  8265. SDX::GetMainChanges($main::BuildNumber, "MAIN");
  8266. #
  8267. # get changes from the IDX build
  8268. #
  8269. # for idx builds there's only one contributing branch, idx0N
  8270. # use the first one in the list
  8271. #
  8272. my $branch = (grep {/idx/} @{$main::BuildHistory{$main::BuildNumber}{branches}})[0];
  8273. SDX::GetBranchChanges($main::BuildNumber, $branch, $type);
  8274. };
  8275. }
  8276. }
  8277. # _____________________________________________________________________________
  8278. #
  8279. # GetMainChanges
  8280. #
  8281. # Parameters:
  8282. #
  8283. # Output:
  8284. # _____________________________________________________________________________
  8285. sub GetMainChanges
  8286. {
  8287. my $buildnum = $_[0];
  8288. my $type = $_[1];
  8289. my $labbranch = "";
  8290. #
  8291. # get changes that went into //depot/main for this build
  8292. #
  8293. SDX::GetBranchChanges($buildnum, "main", $type);
  8294. #
  8295. # for each lab that RI'd, get changes that went into //depot/<lab>
  8296. #
  8297. my %seen = ();
  8298. my @labbranches = sort grep {/lab/} @{$main::BuildHistory{$buildnum}{branches}};
  8299. foreach $labbranch (@labbranches)
  8300. {
  8301. $seen{$labbranch} and next;
  8302. $seen{$labbranch} = 1;
  8303. SDX::GetBranchChanges($buildnum, $labbranch, $type);
  8304. }
  8305. }
  8306. # _____________________________________________________________________________
  8307. #
  8308. # GetBranchChanges
  8309. #
  8310. # Parameters:
  8311. #
  8312. # Output:
  8313. # _____________________________________________________________________________
  8314. sub GetBranchChanges
  8315. {
  8316. my $buildnum = $_[0];
  8317. my $branch = $_[1];
  8318. my $type = $_[2];
  8319. my $project = "";
  8320. $main::Logging = $main::TRUE;
  8321. $main::Log = "$main::SDXRoot\\changes.$buildnum.$branch.txt";
  8322. unlink $main::Log;
  8323. print "\n\n\nGetting changes for $buildnum $branch...\n";
  8324. #
  8325. # get changes that went into //depot/$branch for $buildnum
  8326. #
  8327. # for each project
  8328. # get ts1, ts2
  8329. # get change list
  8330. #
  8331. foreach $proj (@main::SDMapProjects)
  8332. {
  8333. my $ts1 = "";
  8334. my $ts2 = "";
  8335. $project = "\l@$proj[0]";
  8336. my $header = "\n---------------- \U$project\n";
  8337. #
  8338. # skip this project if the user negated it on the cmd line
  8339. #
  8340. $main::UserArgs =~ /~$project / and next;
  8341. #
  8342. # get path to SD.INI, make sure we have it, and cd there
  8343. #
  8344. $fpr = $main::SDXRoot . "\\" . @$proj[1];
  8345. $sdini = $fpr . "\\sd.ini";
  8346. (-e $sdini) or (print "$header\nCan't find $sdini.\n" and next);
  8347. chdir $fpr or die("\nCan't cd to $fpr.\n");
  8348. #
  8349. # ts1, ts2 depend on build type
  8350. #
  8351. ($type eq "BETA") and ($ts1, $ts2, $header) = SDX::GetBetaTimestamps($buildnum, $branch, $project, $header);
  8352. ($type eq "IDX") and ($ts1, $ts2, $header) = SDX::GetIDXTimestamps($buildnum, $branch, $project, $header);
  8353. ($type eq "MAIN") and ($ts1, $ts2, $header) = SDX::GetMainTimestamps($buildnum, $branch, $project, $header);
  8354. $ts1 = "\@$ts1";
  8355. $ts2 = ($type eq "IDX" and $ts2 eq "CURRENT") ? "" : "\@$ts2";
  8356. #
  8357. # list changes
  8358. #
  8359. my $spec = "//depot/$branch/$project/...$ts1,$ts2";
  8360. my $cmd = "sd.exe changes $spec 2>&1";
  8361. $header .= "Getting changes for $spec\n\n";
  8362. SDX::RunSDCmd($header, $cmd);
  8363. }
  8364. }
  8365. # _____________________________________________________________________________
  8366. #
  8367. # GetMainTimestamps
  8368. #
  8369. # Parameters:
  8370. #
  8371. # Output:
  8372. # _____________________________________________________________________________
  8373. sub GetMainTimestamps
  8374. {
  8375. my $buildnum = $_[0];
  8376. my $branch = $_[1];
  8377. my $project = $_[2];
  8378. my $header = $_[3];
  8379. my %bh = %main::BuildHistory;
  8380. my @ts = (); my $ts1 = ""; my $ts2 = ""; my $op = "";
  8381. =begin comment text
  8382. to trace integration records:
  8383. build contrib
  8384. build type op branch branch project change/timestamp
  8385. ----- ---- --- ------ ------- ---------- -------------------------
  8386. 2268 MAIN RI main lab07_n admin 15654 2000/09/08:17:00:04
  8387. 2268 MAIN RI main lab07_n base 10928 2000/09/08:17:00:21
  8388. 2268 MAIN RI main lab07_n com 1755 2000/09/08:17:00:29
  8389. 2268 MAIN RI main lab07_n ds 4124 2000/09/08:17:00:54
  8390. 2268 MAIN RI main lab07_n enduser 19639 2000/09/08:17:00:59
  8391. 2268 MAIN RI main lab07_n inetsrv 1503 2000/09/08:17:01:23
  8392. 2268 MAIN RI main lab07_n root 25483 2000/09/08:17:02:06
  8393. in Admin
  8394. sd describe -s 15654
  8395. for each file in the RI
  8396. sd changes //depot/lab07_n/admin/path/to/file.ext@ts1,@ts2
  8397. throw away data prior to ts1
  8398. push "change" lines ont list
  8399. sort, unique
  8400. print
  8401. [\\JEFFMCD5 E:\nt\admin] sd describe -s 15654 | qgrep -e integrate | awk "{print \"sd changes \"$2\"@2000/08/0
  8402. 3:17:15:40,@2000/09/08:17:00:04\"}" | sed "s/#[0-9]+//g" | sed "s/\/main\//\/lab07_n\//g" | cmd.exe >>15654
  8403. [\\JEFFMCD5 E:\nt\admin] g Change 15654 | unique | sort /R
  8404. =end comment text
  8405. =cut
  8406. #
  8407. # main branch timestamps
  8408. #
  8409. ($branch eq "main") and do
  8410. {
  8411. #
  8412. # ts1 =
  8413. #
  8414. # time of most recent event in Main (RI checkin, or integration to IDX/Beta branch)
  8415. # for the build prior to the build in question
  8416. # in //depot/main/$project
  8417. # for all branches that contributed
  8418. #
  8419. # if no data for $project, default to Root
  8420. #
  8421. my $build = $buildnum - 1;
  8422. my $p = $project;
  8423. ($ts1, $op) = SDX::GetMainTS1($build, $p);
  8424. (!$ts1) and do
  8425. {
  8426. $p = "root";
  8427. ($ts1, $op) = SDX::GetMainTS1($build, $p);
  8428. };
  8429. $main::V2 and $header .= "ts1 = $build $branch $p $op = $ts1\n";
  8430. #
  8431. # ts2 =
  8432. #
  8433. # time of event in Main (initial RI checkin if RI/IDX, or initial integration if BETA)
  8434. # for the build following the build in question
  8435. # in //depot/main/$project
  8436. # for all branches that contributed
  8437. # less five minutes
  8438. # OR
  8439. #
  8440. # time of final RI checkin
  8441. # for the build in question
  8442. # for all branches that contributed
  8443. #
  8444. # if no data for $project, default to Root
  8445. #
  8446. @ts = ();
  8447. $build = $buildnum + 1;
  8448. $p = $project;
  8449. ($ts2, $op) = SDX::GetMainTS2($build, $p);
  8450. (!$ts2) and do
  8451. {
  8452. $p = "root";
  8453. ($ts2, $op) = SDX::GetMainTS2($build, $p);
  8454. };
  8455. #
  8456. # subtract 5 minutes if not using current build
  8457. #
  8458. ($build != $buildnum) and $ts2 = SDX::IncrDecrTS($ts2, 0, -5, 0);
  8459. $main::V2 and $header .= "ts2 = $build $branch $p $op = $ts2\n";
  8460. };
  8461. #
  8462. # lab branch timestamps
  8463. #
  8464. ($branch =~ /lab/) and do
  8465. {
  8466. my @builds = sort keys %bh; my $first = @builds[0];
  8467. my $p = $project;
  8468. #
  8469. # ts1 = time of last RI checkin of this VBL into Main
  8470. #
  8471. # default to current build Root RI time, less 10 min, if no data
  8472. #
  8473. for ($prev = $buildnum - 1; $prev > $first; $prev--)
  8474. {
  8475. (exists($bh{$prev}{main}{$branch}{$p})) and do
  8476. {
  8477. push @ts, $bh{$prev}{main}{$branch}{$p}[1];
  8478. last;
  8479. };
  8480. }
  8481. @ts = reverse sort @ts;
  8482. @ts and $ts1 = @ts[0];
  8483. (!$ts1) and do
  8484. {
  8485. $p = "root"; $prev = $buildnum;
  8486. @ts = @{$bh{$buildnum}{main}{$branch}{$p}};
  8487. $ts1 = @ts[$#ts];
  8488. $ts1 = SDX::IncrDecrTS($ts1, 0, -10, 0);
  8489. };
  8490. $main::V2 and $header .= "ts1 = $prev $branch $p RI = $ts1\n";
  8491. #
  8492. # ts2 = time of final RI checkin for this VBL into Main
  8493. #
  8494. # default to Root if no data for this project
  8495. #
  8496. $p = $project;
  8497. @ts = @{$bh{$buildnum}{main}{$branch}{$p}};
  8498. $ts2 = @ts[$#ts];
  8499. (!$ts2) and do
  8500. {
  8501. $p = "root";
  8502. @ts = @{$bh{$buildnum}{main}{$branch}{$p}};
  8503. $ts2 = @ts[$#ts];
  8504. };
  8505. $main::V2 and $header .= "ts2 = $buildnum $branch $p RI = $ts2\n";
  8506. };
  8507. (!$main::V2 and !($ts1 and $ts2)) and do
  8508. {
  8509. my $ts = !$ts1 ? "ts1" : "ts2";
  8510. die("\n\nGetMainTimestamps: missing $ts for $buildnum $branch $project.\n");
  8511. };
  8512. return ($ts1, $ts2, $header);
  8513. }
  8514. # _____________________________________________________________________________
  8515. #
  8516. # GetMainTS1
  8517. #
  8518. # Parameters:
  8519. #
  8520. # Output:
  8521. # _____________________________________________________________________________
  8522. sub GetMainTS1
  8523. {
  8524. my $build = $_[0];
  8525. my $project = $_[1];
  8526. my %bh = %main::BuildHistory;
  8527. my $bt = ""; my $op = ""; my @ts = ();
  8528. #
  8529. # return if no data for this build
  8530. #
  8531. (!($bt = $bh{$build}{buildtype})) and return "";
  8532. ($bt eq "MAIN") and do
  8533. {
  8534. my @labbranches = grep {/lab/} keys %main::AllBranches;
  8535. $op = "RI";
  8536. foreach (@labbranches) { (exists($bh{$build}{main}{$_}{$project})) and push @ts, $bh{$build}{main}{$_}{$project}[1]; }
  8537. };
  8538. ($bt eq "BETA") and do
  8539. {
  8540. my @betabranches = grep {/beta/} keys %main::AllBranches;
  8541. $op = "INT";
  8542. foreach (@betabranches) { (exists($bh{$build}{$_}{$_}{$project})) and push @ts, $bh{$build}{$_}{$_}{$project}[1]; }
  8543. };
  8544. ($bt eq "IDX") and do
  8545. {
  8546. my @idxbranches = grep {/idx/} keys %main::AllBranches;
  8547. $op = "INT";
  8548. foreach (@idxbranches) { (exists($bh{$build}{$_}{$_}{$project})) and push @ts, $bh{$build}{$_}{$_}{$project}[1]; }
  8549. };
  8550. #
  8551. # sort and reverse so final timestamp is first
  8552. #
  8553. @ts = reverse sort @ts;
  8554. return (@ts[0], $op);
  8555. }
  8556. # _____________________________________________________________________________
  8557. #
  8558. # GetMainTS2
  8559. #
  8560. # Parameters:
  8561. #
  8562. # Output:
  8563. # _____________________________________________________________________________
  8564. sub GetMainTS2
  8565. {
  8566. my $build = $_[0];
  8567. my $project = $_[1];
  8568. my %bh = %main::BuildHistory;
  8569. my $bt = ""; my $op = ""; my @ts = ();
  8570. #
  8571. # return if no data for this build
  8572. #
  8573. (!($bt = $bh{$build}{buildtype})) and return "";
  8574. #
  8575. # in the case of MAIN or IDX, we want the time of the blueline build
  8576. #
  8577. ($bt eq "MAIN" or $bt eq "IDX") and do
  8578. {
  8579. my @labbranches = grep {/lab/} keys %main::AllBranches;
  8580. $op = "RI";
  8581. foreach (@labbranches) { (exists($bh{$build}{main}{$_}{$project})) and push @ts, $bh{$build}{main}{$_}{$project}[$#{$bh{$build}{main}{$_}{$project}}]; }
  8582. };
  8583. ($bt eq "BETA") and do
  8584. {
  8585. my @betabranches = grep {/beta/} keys %main::AllBranches;
  8586. $op = "INT";
  8587. foreach (@betabranches) { (exists($bh{$build}{$_}{$_}{$project})) and push @ts, $bh{$build}{$_}{$_}{$project}[$#{$bh{$build}{$_}{$_}{$project}}]; }
  8588. };
  8589. #
  8590. # sort so the initial timestamp is first
  8591. # and return it
  8592. #
  8593. @ts = sort @ts;
  8594. return (@ts[0], $op);
  8595. }
  8596. # _____________________________________________________________________________
  8597. #
  8598. # GetBetaTimestamps
  8599. #
  8600. # Parameters:
  8601. #
  8602. # Output:
  8603. # _____________________________________________________________________________
  8604. sub GetBetaTimestamps
  8605. {
  8606. my $buildnum = $_[0];
  8607. my $branch = $_[1];
  8608. my $project = $_[2];
  8609. my $header = $_[3];
  8610. my %bh = %main::BuildHistory;
  8611. #
  8612. # ts1 = time of the most recent Beta build's RI to Main for this project
  8613. #
  8614. # OR
  8615. # earliest time of last full integration from Main to this branch for this project
  8616. #
  8617. my $ts1 = ""; my @ts = ();
  8618. my $prev = $buildnum - 1;
  8619. my @builds = sort keys %bh; my $first = @builds[0];
  8620. #
  8621. # look for the last build in which this project RI'd to Main
  8622. #
  8623. for ($prev = $buildnum - 1; $prev > $first; $prev--)
  8624. {
  8625. if (@ts = @{$bh{$prev}{main}{$branch}{$project}})
  8626. {
  8627. $ts1 = @ts[1];
  8628. $main::V2 and $header .= "ts1 = $prev $branch $project RI = $ts1\n";
  8629. last;
  8630. }
  8631. }
  8632. #
  8633. # otherwise find the last full integration from Main for this project
  8634. #
  8635. (!$ts1) and do
  8636. {
  8637. for ($prev = $buildnum; $prev > $first; $prev--)
  8638. {
  8639. if (@ts = @{$bh{$prev}{$branch}{$branch}{$project}})
  8640. {
  8641. $ts1 = @ts[$#ts];
  8642. $main::V2 and $header .= "ts1 = $prev $branch $project INT = $ts1\n";
  8643. last;
  8644. }
  8645. }
  8646. };
  8647. #
  8648. # ts2 = time of the final RI to Main of the build in question
  8649. #
  8650. # OR
  8651. # if no timestamp for this project, use Root's, it's close enough
  8652. #
  8653. my $p = $project;
  8654. @ts = @{$bh{$buildnum}{main}{$branch}{$project}};
  8655. my $ts2 = @ts[$#ts];
  8656. !$ts2 and do
  8657. {
  8658. $p = "root";
  8659. @ts = @{$bh{$buildnum}{main}{$branch}{$p}};
  8660. $ts2 = @ts[$#ts];
  8661. };
  8662. $main::V2 and $header .= "ts2 = $buildnum $branch $p RI = $ts2\n";
  8663. (!$main::V2 and !($ts1 and $ts2)) and do
  8664. {
  8665. my $ts = !$ts1 ? "ts1" : "ts2";
  8666. die("\n\nGetBetaTimestamps: missing $ts for $buildnum $branch $project.\n");
  8667. };
  8668. return ($ts1, $ts2, $header);
  8669. }
  8670. # _____________________________________________________________________________
  8671. #
  8672. # GetIDXTimestamps
  8673. #
  8674. # Parameters:
  8675. #
  8676. # Output:
  8677. # _____________________________________________________________________________
  8678. sub GetIDXTimestamps
  8679. {
  8680. my $buildnum = $_[0];
  8681. my $branch = $_[1];
  8682. my $project = $_[2];
  8683. my $header = $_[3];
  8684. my %bh = %main::BuildHistory;
  8685. my $prev; my $next;
  8686. my @ts = (); my $ts1 = ""; my $ts2 = "";
  8687. my @builds = sort keys %bh; my $first = @builds[0]; my $last = @builds[$#builds];
  8688. #
  8689. # ts1 = time of most recent INT from Main
  8690. # to this IDX branch
  8691. # for $project
  8692. # OR
  8693. # default to current build Root integration
  8694. #
  8695. my $p = $project;
  8696. for ($prev = $buildnum; $prev >= $first; $prev--)
  8697. {
  8698. if (@ts = @{$bh{$prev}{$branch}{$branch}{$p}})
  8699. {
  8700. $ts1 = @ts[1];
  8701. last;
  8702. }
  8703. }
  8704. (!$ts1) and do
  8705. {
  8706. $prev = $buildnum;
  8707. $p = "root";
  8708. $ts1 = @{$bh{$buildnum}{$branch}{$branch}{$p}}[1];
  8709. };
  8710. $main::V2 and $header .= "ts1 = $prev $branch $p INT = $ts1\n";
  8711. #
  8712. # ts2 = time of next full integration
  8713. # to this IDX branch
  8714. # for $project
  8715. # less 5 min,
  8716. # OR
  8717. # default to current state if no integration found
  8718. #
  8719. for ($next = $buildnum + 1; $next <= $last; $next++)
  8720. {
  8721. if (@ts = @{$bh{$next}{$branch}{$branch}{$project}})
  8722. {
  8723. $ts2 = @ts[1];
  8724. last;
  8725. }
  8726. }
  8727. if ($ts2)
  8728. {
  8729. $ts2 = SDX::IncrDecrTS($ts2, 0, -5, 0);
  8730. }
  8731. else
  8732. {
  8733. $next = $buildnum;
  8734. $ts2 = "CURRENT";
  8735. }
  8736. $main::V2 and $header .= "ts2 = $next $branch $project INT = $ts2\n";
  8737. #
  8738. # verify and return
  8739. #
  8740. (!$main::V2 and !($ts1 and $ts2)) and do
  8741. {
  8742. my $ts = !$ts1 ? "ts1" : "ts2";
  8743. die("\n\nGetIDXTimestamps: missing $ts for $buildnum $branch $project.\n");
  8744. };
  8745. return ($ts1, $ts2, $header);
  8746. }
  8747. # _____________________________________________________________________________
  8748. #
  8749. # IncrDecrTS
  8750. #
  8751. # Parameters:
  8752. #
  8753. # Output:
  8754. # _____________________________________________________________________________
  8755. sub IncrDecrTS
  8756. {
  8757. use Time::Local;
  8758. my ($ts, $dhour, $dmin, $dsec) = (@_);
  8759. (!$ts) and die("\nIncrDecrTS: null timestamp. Probably missing some build history.\n");
  8760. #
  8761. # convert delta h/m/s to seconds
  8762. #
  8763. $dhour *= 3600;
  8764. $dmin *= 60;
  8765. #
  8766. # split $ts and convert to Epoch seconds
  8767. #
  8768. my ($year, $month, $day, $hour, $min, $sec) = split(/[:\/]/, $ts);;
  8769. $month--;
  8770. my $epoch = timelocal($sec, $min, $hour, $day, $month, $year);
  8771. #
  8772. # add/sub to Epoch seconds
  8773. #
  8774. $epoch += $dhour + $dmin + $dsec;
  8775. #
  8776. # convert Epoch seconds to y/m/d/h/m/s
  8777. #
  8778. ($sec, $min, $hour, $day, $month, $year, $wday, $yday, $isdst) = localtime($epoch);
  8779. $year += 1900;
  8780. $month++;
  8781. # print "$year, $month, $day, $hour, $min, $sec [$wday, $yday, $isdst]\n";
  8782. #
  8783. # join into new $ts
  8784. #
  8785. $ts = "$year/$month/$day:$hour:$min:$sec";
  8786. return $ts;
  8787. }
  8788. # _____________________________________________________________________________
  8789. #
  8790. # GetBuildHistory
  8791. #
  8792. # Parameters:
  8793. #
  8794. # Output:
  8795. #
  8796. # A hash table and indices. Here's the output for sdx changes -b 2271
  8797. # for Root:
  8798. #
  8799. # build contrib
  8800. # build type op branch branch project change/timestamp
  8801. # ----- ---- --- ------ ------- ---------- -------------------------
  8802. # 2255 MAIN RI main lab06_n root 21432 2000/07/31:16:26:53
  8803. # 2256 MAIN RI main lab07_n root 21857 2000/08/03:17:16:27
  8804. # 2257 MAIN RI main lab01_n root 22110 2000/08/07:19:35:50 22108 2000/08/07:19:24:09
  8805. # 2258 MAIN RI main lab02_n root 22392 2000/08/09:22:36:41
  8806. # 2259 MAIN RI main lab04_n root 22581 2000/08/11:14:05:28
  8807. # 2260 MAIN RI main lab06_n root 22889 2000/08/15:16:27:53
  8808. # 2261 MAIN RI main lab03_n root 23320 2000/08/18:15:01:08
  8809. # 2262 MAIN RI main lab02_n root 23634 2000/08/22:20:57:20
  8810. # 2263 MAIN RI main lab06_n root 23779 2000/08/23:20:47:21 23778 2000/08/23:20:23:14
  8811. # 2264 IDX INT idx02 idx02 root 24368 2000/08/29:12:14:53
  8812. # 2264 IDX RI main lab01_n root 24060 2000/08/25:21:32:19
  8813. # 2265 MAIN RI main lab04_n root 24730 2000/08/31:15:05:24
  8814. # 2266 MAIN RI main lab03_n root 24901 2000/09/01:17:02:46
  8815. # 2267 IDX INT idx01 idx01 root 25433 2000/09/08:12:22:27
  8816. # 2267 IDX RI main lab02_n root 25230 2000/09/06:21:36:33
  8817. # 2268 MAIN RI main lab07_n root 25483 2000/09/08:17:02:06
  8818. # 2269 MAIN RI main lab01_n root 25714 2000/09/11:21:05:15 25710 2000/09/11:20:31:44
  8819. # 2269 MAIN RI main lab04_n root 25714 2000/09/11:21:05:15 25710 2000/09/11:20:31:44
  8820. # 2270 MAIN RI main lab06_n root 26211 2000/09/16:13:43:41
  8821. # 2271 MAIN RI main lab02_n root 26594 2000/09/19:20:21:00
  8822. # 2271 MAIN RI main lab03_n root 26602 2000/09/19:20:54:23
  8823. # 2271 MAIN RI main lab07_n root 26585 2000/09/19:19:45:39 26583 2000/09/19:19:42:38
  8824. # 2272 MAIN RI main lab01_n root 26732 2000/09/20:19:19:54
  8825. # 2272 MAIN RI main lab04_n root 26739 2000/09/20:21:05:27
  8826. # 2273 BETA INT beta1 beta1 root 26744 2000/09/20:22:15:52 26744 2000/09/20:22:15:52 26717 2000/09/20:16:59:39
  8827. # 2273 BETA RI main beta1 root 27091 2000/09/23:18:32:20
  8828. # 2274 BETA RI main beta1 root 27255 2000/09/25:22:46:33
  8829. # 2275 BETA RI main beta1 root 27365 2000/09/26:18:03:00
  8830. # 2276 BETA RI main beta1 root 27524 2000/09/27:17:25:33
  8831. # 2277 BETA RI main beta1 root 27641 2000/09/28:16:54:01
  8832. # 2278 BETA RI main beta1 root 27784 2000/09/29:17:25:06
  8833. # 2280 BETA RI main beta1 root 28077 2000/10/03:16:18:28 28027 2000/10/03:12:02:17 27960 2000/10/02:21:24:52 27952 2000/10/02:19:35:15
  8834. # 2281 BETA RI main beta1 root 28112 2000/10/03:17:17:41 28109 2000/10/03:17:16:26 28107 2000/10/03:17:12:09
  8835. # _____________________________________________________________________________
  8836. sub GetBuildHistory
  8837. {
  8838. my $buildnum = $_[0];
  8839. my %bh = ();
  8840. my %br = ();
  8841. my $sdchanges = "sd.exe changes -m 500";
  8842. $main::BuildBranches = ();
  8843. $main::AllBranches = ();
  8844. #
  8845. # do a quick check in Main for RI/Int'n changes and bail
  8846. # if no data for this build
  8847. #
  8848. chdir $main::SDXRoot;
  8849. (!(grep {/ $main::BuildNumber /} grep {/'(RI|INT)[:]*/} `$sdchanges //depot/main/...`)) and do
  8850. {
  8851. print "\nNo build history for $main::BuildNumber found in RI/integration change comments.\n";
  8852. return 0;
  8853. };
  8854. print "\nGetting build history...";
  8855. foreach $proj (@main::SDMapProjects)
  8856. {
  8857. my $project = "\l@$proj[0]";
  8858. my $header = "\n---------------- \U$project\n";
  8859. #
  8860. # skip this project if the user negated it on the cmd line
  8861. #
  8862. $main::UserArgs =~ /~$project / and next;
  8863. #
  8864. # get path to SD.INI, make sure we have it, and cd there
  8865. #
  8866. $fpr = $main::SDXRoot . "\\" . @$proj[1];
  8867. $sdini = $fpr . "\\sd.ini";
  8868. (-e $sdini) or (print "$header\nCan't find $sdini.\n" and next);
  8869. chdir $fpr or die("\nCan't cd to $fpr.\n");
  8870. $main::V3 and print $header;
  8871. print "\n $project";
  8872. =begin comment text
  8873. # use this to fix change comments missing ri/i records:
  8874. my @main = grep {/$main::BuildNumber/i} `$sdchanges //depot/main/$project/...`;
  8875. foreach (@main)
  8876. {
  8877. $ch = (split(/ /, $_))[1];
  8878. print "\n$ch: $_";
  8879. system "sd.exe change -f $ch";
  8880. }
  8881. next;
  8882. =end comment text
  8883. =cut
  8884. #
  8885. # cast back in the major branches for integration/RI changes
  8886. #
  8887. # BUGBUG: change this to get last 500 ** from @1,@<timestamp of $main::BuildNumber> **
  8888. #
  8889. my @main = grep {/'RI[:]*/i} `$sdchanges //depot/main/$project/...`; print ".";
  8890. my @idx01 = grep {/'INT[:]*/i} `$sdchanges //depot/idx01/$project/...`; print ".";
  8891. my @idx02 = grep {/'INT[:]*/i} `$sdchanges //depot/idx02/$project/...`; print ".";
  8892. my @beta1 = grep {/'INT[:]*/i} `$sdchanges //depot/beta1/$project/...`; print ".";
  8893. #
  8894. # hash of pointers to changelist arrays
  8895. #
  8896. %main::BuildBranches = (main => \@main, idx01 => \@idx01, idx02 => \@idx02, beta1 => \@beta1, beta2 => \@beta2);
  8897. #
  8898. # populate the hash
  8899. #
  8900. # for each build branch
  8901. # for each change
  8902. # extract change number and timestamp
  8903. # extract build number
  8904. # extract branch(es)
  8905. # for each contributing lab branch
  8906. # store change number, timestamp
  8907. # also store branch names seen
  8908. # also keep track of branches affecting the build in question
  8909. #
  8910. while ($bb = each %main::BuildBranches)
  8911. {
  8912. # print ".";
  8913. foreach (@{$main::BuildBranches{$bb}})
  8914. {
  8915. $main::V3 and print "$_";
  8916. my @f = split(/ /,$_);
  8917. $change = @f[1];
  8918. $ts = "@f[3]:@f[4]";
  8919. #
  8920. # munge the comment field to get build # and branch(es) involved
  8921. #
  8922. @f = split(/'/,$_); @f = split(/ /, @f[1]);
  8923. my @bn = grep {/[0-9][0-9[0-9][0-9][,;:-]*$/} @f; $bn = @bn[0]; $bn =~ s/[,;:-]//g;
  8924. #
  8925. #$bn =~ /^(22[78][0-9]|2269)/ and next;
  8926. #print "bn = '$bn'\n";
  8927. #
  8928. # for each branch in the comment, save this changenum/ts
  8929. #
  8930. @branches = grep {/(lab|idx|beta)/i} @f;
  8931. foreach $br (@branches)
  8932. {
  8933. #
  8934. # always lowercase, and lab branches
  8935. # must end in _n
  8936. #
  8937. $br = "\l$br";
  8938. ($br =~ /lab/) and do { $br =~ s/_n//g; $br .= "_n"; };
  8939. $main::V3 and print " $bn, $bb, $br, $project = ($change $ts)\n";
  8940. push @{$bh{$bn}{$bb}{$br}{$project}}, ($change,$ts);
  8941. # store branch name
  8942. $main::AllBranches{"\l$br"} = 1;
  8943. push @{$bh{$bn}{branches}}, $br;
  8944. }
  8945. }
  8946. $main::V3 and print "\n";
  8947. }
  8948. }
  8949. print "\n\n";
  8950. #
  8951. # figure out build types
  8952. #
  8953. foreach $bn (sort keys %bh)
  8954. {
  8955. my @btb = @{$bh{$bn}{branches}};
  8956. (grep {/lab/} @btb) and $bh{$bn}{buildtype} = "MAIN";
  8957. (grep {/beta/} @btb) and $bh{$bn}{buildtype} = "BETA";
  8958. (grep {/idx/} @btb) and $bh{$bn}{buildtype} = "IDX";
  8959. }
  8960. ($main::V2) and do
  8961. {
  8962. SDX::PrintBH(\%bh, 0);
  8963. print "\n all build branches: "; foreach $br (sort keys %main::BuildBranches) { print "'$br' "; }
  8964. print "\n all lab branches: "; foreach $br (sort keys %main::AllBranches) { print "'$br' "; }
  8965. print "\n $buildnum type = '$bh{$buildnum}{buildtype}'\n";
  8966. };
  8967. %main::BuildHistory = %bh;
  8968. return 1;
  8969. }
  8970. # _____________________________________________________________________________
  8971. #
  8972. # PrintBH
  8973. #
  8974. # Parameters:
  8975. #
  8976. # Output:
  8977. # _____________________________________________________________________________
  8978. sub PrintBH
  8979. {
  8980. my ($bh, $buildnum) = @_;
  8981. print "\n";
  8982. #
  8983. # if we have a specific build number, print just its data
  8984. # else print the entire history
  8985. #
  8986. my $op = "";
  8987. my @bh2 = ();
  8988. my @builds = $buildnum ? ("$buildnum") : sort keys %$bh;
  8989. my @buildbranches = sort keys %main::BuildBranches;
  8990. my @allbranches = sort keys %main::AllBranches;
  8991. foreach $bn (@builds)
  8992. {
  8993. foreach $bb (@buildbranches)
  8994. {
  8995. foreach $br (@allbranches)
  8996. {
  8997. foreach (@main::SDMapProjects)
  8998. {
  8999. my $p = @$_[0];
  9000. $op = $bb eq "main" ? "RI" : "INT";
  9001. (exists($$bh{$bn}{$bb}{$br}{$p})) and push @bh2, sprintf " %-5s %-4s %-3s %-6s %-7s %-10s @{$$bh{$bn}{$bb}{$br}{$p}}\n", $bn, $$bh{$bn}{buildtype}, $op, $bb, $br, $p;
  9002. }
  9003. }
  9004. }
  9005. }
  9006. print " build contrib\n";
  9007. print " build type op branch branch project change/timestamp\n";
  9008. print " ----- ---- --- ------ ------- ---------- -------------------------\n";
  9009. @bh2 = sort @bh2;
  9010. foreach (@bh2) { print "$_"; }
  9011. print "\n\n";
  9012. }
  9013. # _____________________________________________________________________________
  9014. #
  9015. # GetActiveBranches
  9016. #
  9017. # Parameters:
  9018. #
  9019. # Output:
  9020. # _____________________________________________________________________________
  9021. sub GetActiveBranches
  9022. {
  9023. =begin comment text
  9024. [\\JEFFMCD5 E:\nt] sd files //depot/*/root/* | qgrep -v -e delete -e /main | sed "s/\// /g" | awk "{print $2}"
  9025. | sort | unique
  9026. beta1
  9027. idx01
  9028. idx02
  9029. Lab01_N
  9030. lab01_n-vc
  9031. Lab01_N+1
  9032. Lab02_N
  9033. Lab02_N+1
  9034. Lab03_N
  9035. Lab03_N+1
  9036. Lab04_N
  9037. Lab04_N+1
  9038. Lab06_N
  9039. Lab06_N+1
  9040. Lab07_N
  9041. Lab07_N+1
  9042. Lab21_N
  9043. =end comment text
  9044. =cut
  9045. }
  9046. # _____________________________________________________________________________
  9047. #
  9048. # VerifySubmitComment
  9049. #
  9050. # Parameters:
  9051. #
  9052. # Output:
  9053. # _____________________________________________________________________________
  9054. sub VerifySubmitComment
  9055. {
  9056. #
  9057. # if user is RI'g or integrating, standardize comment
  9058. # RI: <lab(s)> <buildnum> <user-text>
  9059. # INT: <lab(s)> <buildnum> <user-text>
  9060. #
  9061. ($main::MinusR or $main::MinusT) and do
  9062. {
  9063. my $sc = $main::SubmitComment; $sc =~ s/\+/PLUS/g;
  9064. my @f = split(/ /, $sc);
  9065. # RI:/INT:
  9066. my $op = $main::MinusR ? "RI:" : "INT:";
  9067. # branch(es)
  9068. my @branches = grep {/(lab|idx|beta)/i} @f;
  9069. if (!@branches)
  9070. {
  9071. print "\nMissing branch.\n";
  9072. print "\nSubmit comment must include the branch(es) being (reverse) integrated. Valid\n";
  9073. print "branch names are beta1, idx01, idx02, lab01_n, lab07_n+1, etc.\n";
  9074. die("\n");
  9075. }
  9076. else
  9077. {
  9078. #
  9079. # strip out redundant branch names
  9080. #
  9081. my %uniq = ();
  9082. foreach (@branches) { $uniq{$_} = 1; }
  9083. @branches = sort keys %uniq;
  9084. #
  9085. # strip name from original comment, avoid duplicates
  9086. #
  9087. foreach (@branches) { $sc =~ s/$_//g; }
  9088. #
  9089. # for bare lab branches, add _n
  9090. #
  9091. foreach (@branches) { ($_ =~ /lab[0-9][0-9]$/) and $_ .= "_n"; }
  9092. $branches = join ' ', @branches;
  9093. }
  9094. # build number
  9095. @bn = grep {/[0-9][0-9][0-9][0-9][,:;-]*/} @f; my $bn = @bn[0]; $bn =~ s/[,:;-]*//g;
  9096. if (!$bn)
  9097. {
  9098. print "\nMissing build number.\n";
  9099. print "\nSubmit comment must include the build number being (reverse) integrated.\n";
  9100. die("\n");
  9101. }
  9102. else
  9103. {
  9104. # strip buildnum from original comment
  9105. $sc =~ s/$bn//g;
  9106. }
  9107. $sc = "$op $branches $bn $sc";
  9108. $sc =~ s/PLUS/\+/g; $sc =~ s/[\t\s]+/ /g;
  9109. $main::SubmitComment = $sc;
  9110. $main::V2 and print "comment = '$main::SubmitComment'\n";
  9111. };
  9112. }
  9113. #
  9114. # if we get here, something's wrong
  9115. #
  9116. 1;