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

10724 lines
309 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. diff2 => {fn => \&OtherOp, defcmd => "diff2", defarg => "", type => 1,},
  188. dirs => {fn => \&OtherOp, defcmd => "dirs", defarg => "", type => 1,}, # project depot
  189. files => {fn => \&OtherOp, defcmd => "files", defarg => "", type => 1,}, # project project
  190. have => {fn => \&OtherOp, defcmd => "have", defarg => "", type => 1,}, # project project
  191. info => {fn => \&OtherOp, defcmd => "info", defarg => "", type => 1,}, # project depot
  192. integrated => {fn => \&OtherOp, defcmd => "integrated", defarg => "", type => 1,}, # project depot
  193. labels => {fn => \&OtherOp, defcmd => "labels", defarg => "", type => 1,}, # project depot
  194. opened => {fn => \&OtherOp, defcmd => "opened", defarg => "", type => 1,}, # project project
  195. pending => {fn => \&OtherOp, defcmd => "changes", defarg => "-s pending", type => 1,}, # project depot
  196. projects => {fn => \&OtherOp, defcmd => "projects", defarg => "", type => 1,}, # project project
  197. resolved => {fn => \&OtherOp, defcmd => "resolved", defarg => "", type => 1,}, # project depot
  198. status => {fn => \&OtherOp, defcmd => "status", defarg => "", type => 1,}, # project project
  199. # user => {fn => \&OtherOp, defcmd => "user", defarg => "", type => 1,}, # project depot
  200. users => {fn => \&OtherOp, defcmd => "users", defarg => "", type => 1,}, # project depot
  201. where => {fn => \&OtherOp, defcmd => "where", defarg => "", type => 1,}, # project project
  202. #
  203. # internal
  204. #
  205. enumdepots => {fn => \&OtherOp, defcmd => "enumdepots", defarg => "", type => 1,}, # project project
  206. );
  207. #
  208. # list of SD command/flag combinations not to allow
  209. #
  210. %main::BadCmds =
  211. (
  212. #
  213. # -c makes no sense since change numbers aren't consistent across name space
  214. #
  215. -c => [
  216. "integrate",
  217. "revert",
  218. "submit"
  219. ],
  220. #
  221. # don't want any switches to sdx branch/change/user except -o
  222. #
  223. -d => [
  224. "branch",
  225. "change",
  226. "user"
  227. ],
  228. -f => [
  229. "branch",
  230. "change",
  231. "user"
  232. ],
  233. #
  234. # don't want to branch/client/changelist/label/user spec changing with -i
  235. # sd(x) client is ok
  236. #
  237. -i => [
  238. "branch",
  239. "change",
  240. "client",
  241. "submit",
  242. "user"
  243. ],
  244. -t => [
  245. "client",
  246. "label"
  247. ],
  248. );
  249. #
  250. # set the starting dir
  251. #
  252. open(CWD, 'cd 2>&1|');
  253. $main::StartDir = <CWD>;
  254. close(CWD);
  255. chop $main::StartDir;
  256. #
  257. # figure out where we're running from
  258. #
  259. $main::InstallFrom = $ENV{STARTPATH};
  260. #
  261. # parse cmd line
  262. #
  263. SDX::ParseArgs(@_);
  264. #
  265. # return if we need usage already
  266. #
  267. $main::Usage and return;
  268. #
  269. # on new enlists in NT, don't let SDXROOT be > 8.3
  270. #
  271. # BUGBUG-1999/12/01-jeffmcd -- this should be an option in the codebase map -- SHORTROOT = 1
  272. #
  273. ($main::NewEnlist and "\U$main::CodeBase" eq "NT") and do
  274. {
  275. my $root = (split(/\\/, $main::SDXRoot))[1];
  276. (length((split/\./, $root)[0]) > 8 or length((split/\./, $root)[1]) > 3) and die("Please use an 8.3 name for \%SDXROOT\%.\n");
  277. };
  278. #
  279. # does the SD client exist?
  280. #
  281. grep(/ recognized /, `sd.exe 2>&1`) and die("\nCan't find Source Depot client SD.EXE.\n");
  282. #
  283. # SD.MAP contains the relative paths to the roots of all projects the user
  284. # is enlisted in, as created by SDX ENLIST, plus some keywords
  285. #
  286. # if we're doing anything other than enlisting or repairing, this must exist
  287. #
  288. $main::SDMap = "$main::SDXRoot\\sd.map";
  289. #
  290. # get attributes for this enlistment from SD.MAP
  291. #
  292. # fatal error if defecting, incrementally enlisting, or other op
  293. # error text comes from ReadSDMap()
  294. #
  295. $main::Enlisting and $op = "enlist";
  296. $main::Repairing and $op = "repair";
  297. $main::Defecting and $op = "defect";
  298. $main::OtherOp and $op = "otherop";
  299. my $rc = SDX::ReadSDMap($op, "init");
  300. !$rc and ($main::IncrEnlist or $main::Defecting or $main::OtherOp) and die("\n");
  301. #
  302. # if we have codebase and branch values from SD.MAP, use them
  303. #
  304. # handle some special cases
  305. #
  306. ($main::SDMapCodeBase and $main::SDMapBranch and $main::SDMapCodeBaseType) and do
  307. {
  308. #
  309. # on repair, warn the user we're changing these values
  310. #
  311. ($main::Repairing and $main::CodeBase and $main::Branch) and do
  312. {
  313. print "\nUsing codebase and branch from $main::SDMap for repair. Ignoring ";
  314. printf "%s.\n", $main::EnlistFromProfile ? "profile\n$main::Profile" : "'$main::CodeBase $main::Branch'\non command line";
  315. };
  316. #
  317. # if the user is trying to enlist using a profile, they're already enlisted.
  318. # the profile may have different codebase, branch or projects than what they
  319. # already have, so error out
  320. #
  321. # $main::EnlistFromProfile can also be set during a repair
  322. #
  323. ($main::EnlistFromProfile and !$main::Repairing) and do
  324. {
  325. print "\nEnlisting by profile is only supported for new enlistments.\n";
  326. $main::CodeBase = "";
  327. $main::Branch = "";
  328. $main::Usage = $main::TRUE;
  329. return;
  330. };
  331. #
  332. # this may look like a new enlist but is actually incremental
  333. #
  334. # this prevents us from generating a unique client name later on,
  335. # since the user is just adding another project to their enlistment
  336. # and thought they needed to specify cb/br on the cmd line
  337. #
  338. # also prevents enlisting a different codebase or branch in
  339. # this particular SDX Root
  340. #
  341. # repair-from-profile will also have $main::NewEnlist set
  342. #
  343. ($main::NewEnlist and !$main::Repairing) and do
  344. {
  345. print "\nUsing codebase and branch from $main::SDMap. Ignoring '$main::CodeBase $main::Branch'\n";
  346. print "on command line.\n";
  347. $main::NewEnlist = $main::FALSE;
  348. $main::IncrEnlist = $main::TRUE;
  349. };
  350. #
  351. # finally, set primary codebase, type and branch
  352. #
  353. $main::CodeBase = $main::SDMapCodeBase;
  354. $main::CodeBaseType = $main::SDMapCodeBaseType;
  355. $main::Branch = $main::SDMapBranch;
  356. };
  357. #
  358. # at this point we must have codebase, type and branch
  359. #
  360. (!$main::CodeBase or !$main::Branch) and do
  361. {
  362. print "\nMissing codebase and/or branch.\n";
  363. $main::Usage = $main::TRUE;
  364. return;
  365. };
  366. #
  367. # be NT-centric for a minute and see if we know
  368. # about a public change number
  369. #
  370. $main::PublicChangeNum = SDX::GetPublicChangeNum();
  371. #
  372. # if we're working in a type 2 (N projects per depot), modify some
  373. # commands to work per-depot instead of per-project
  374. #
  375. # ie sdx submit on a type 1 should work per-project (which is actually a depot) and
  376. # sdx submit on a type 2 should work per-depot (which encompasses several projects)
  377. #
  378. $main::CodeBaseType == 2 and do
  379. {
  380. $main::SDCmds{admin}{type} = 2;
  381. # $main::SDCmds{branch}{type} = 2;
  382. $main::SDCmds{branches}{type} = 2;
  383. $main::SDCmds{client}{type} = 2;
  384. $main::SDCmds{clients}{type} = 2;
  385. $main::SDCmds{counters}{type} = 2;
  386. $main::SDCmds{dirs}{type} = 2;
  387. $main::SDCmds{info}{type} = 2;
  388. $main::SDCmds{integrate}{type} = 2;
  389. $main::SDCmds{labbranch}{type} = 2;
  390. $main::SDCmds{label}{type} = 2;
  391. $main::SDCmds{labels}{type} = 2;
  392. $main::SDCmds{labelsync}{type} = 2;
  393. $main::SDCmds{pending}{type} = 2;
  394. $main::SDCmds{privatebranch}{type} = 2;
  395. $main::SDCmds{protect}{type} = 2;
  396. $main::SDCmds{submit}{type} = 2;
  397. $main::SDCmds{triggers}{type} = 2;
  398. $main::SDCmds{users}{type} = 2;
  399. #
  400. # these need to stay type 1 b/c they can take a filespec,
  401. # which doesn't make sense when executing per-depot
  402. # since we never leave %SDXROOT%
  403. #
  404. # $main::SDCmds{integrated}{type} = 2;
  405. # $main::SDCmds{resolve}{type} = 2;
  406. # $main::SDCmds{resolved}{type} = 2;
  407. };
  408. #
  409. # fatal if no codebase type and not enlisting clean
  410. #
  411. # on a clean enlist we won't know the type until we have a chance to read $main::CodeBaseMap
  412. #
  413. (!$main::NewEnlist and !$main::Repairing and !$main::CodeBaseType) and die("\nCan't determine codebase type. Please contact the SDX alias.\n");
  414. #
  415. # set SDUSER and SDCLIENT
  416. #
  417. # if SDUSER is already defined in the environment
  418. # assume it includes the domain name, and extract the user name
  419. # otherwise use %USERNAME% and %USERDOMAIN%
  420. #
  421. # if SDCLIENT is already defined, use it, otherwise default to %COMPUTERNAME%.
  422. #
  423. # when defecting or repairing, if SDCLIENT is defined in the env, use it,
  424. # otherwise use main::SDMapClient from SD.MAP. Ignore %COMPUTERNAME% unless we
  425. # have no other choice
  426. #
  427. $main::SDUser = $ENV{SDUSER};
  428. if ($main::SDUser)
  429. {
  430. $main::SDDomainUser = $main::SDUser;
  431. $main::SDUser = (split(/\\/, $main::SDDomainUser))[1];
  432. }
  433. else
  434. {
  435. $main::SDUser = $ENV{USERNAME};
  436. $main::SDDomainUser = "$ENV{USERDOMAIN}\\$main::SDUser";
  437. }
  438. #
  439. # domain can't be computername, that is, user must be logged into the domain
  440. #
  441. ("\U$ENV{USERDOMAIN}" eq "\U$ENV{COMPUTERNAME}") and die("\nTo enlist you must be logged into the domain and not your local machine.\n");
  442. $main::SDClient = $ENV{SDCLIENT};
  443. (!$main::SDClient) and do
  444. {
  445. $main::SDClient = ($main::Defecting or $main::Repairing or $main::IncrEnlist) ? $main::SDMapClient : $ENV{COMPUTERNAME};
  446. #
  447. # we may not be able to get the client name from SD.MAP so assume it's
  448. # just the computer name, we'll catch it later if it isn't
  449. #
  450. $main::Repairing and !$main::SDClient and do
  451. {
  452. print "\nResorting to \%COMPUTERNAME\% for SD client name. Please verify below that\n";
  453. print "this is the correct client for this enlistment before continuing. If not, set\n";
  454. print "\%SDCLIENT\% correctly at the command line and rerun this command.\n";
  455. $main::SDClient = $ENV{COMPUTERNAME};
  456. };
  457. };
  458. !$main::SDUser and die("\nCan't determine SD user name. Verify that %USERNAME% is set in\nthe environment.\n");
  459. !$main::SDClient and die("\nCan't determine SD client name. Verify that %COMPUTERNAME% is set\nin the environment.\n");
  460. $main::V3 and do
  461. {
  462. printf "init: startdir=%s\n", $main::StartDir;
  463. printf "init: startpath=%s\n", $main::StartPath;
  464. printf "init: sdr = '%s'\n", $main::SDXRoot;
  465. printf "init: sdm = '%s'\n", $main::SDMap;
  466. printf "init: sdc = '%s'\n", $main::SDClient;
  467. printf "init: sdu = '%s'\n", $main::SDUser;
  468. printf "init: sddu = '%s'\n", $main::SDDomainUser;
  469. printf "init: usage=%s\n", $main::Usage;
  470. };
  471. $main::Initializing = $main::FALSE;
  472. }
  473. # _____________________________________________________________________________
  474. #
  475. # Parses command line arguments to verify the right syntax is being used
  476. #
  477. # Parameters:
  478. # Command Line Arguments
  479. #
  480. # Output:
  481. # Errors if the wrong syntax is used otherwise sets the appropriate variables
  482. # based on the command line arguments
  483. # _____________________________________________________________________________
  484. sub ParseArgs
  485. {
  486. #
  487. # Initialize variables
  488. #
  489. $ArgCounter = 1; # start at one since 0th arg is redundant
  490. $main::Usage = $main::FALSE;
  491. $main::GetStarted = $main::TRUE;
  492. $main::V1 = $main::FALSE;
  493. $main::V2 = $main::FALSE;
  494. $main::V3 = $main::FALSE;
  495. $main::Enlisting = $main::FALSE;
  496. $main::Defecting = $main::FALSE;
  497. $main::Repairing = $main::FALSE;
  498. $main::OtherOp = $main::TRUE;
  499. $main::EnlistAll = $main::FALSE;
  500. $main::EnlistClean = $main::FALSE;
  501. $main::EnlistGroup = $main::FALSE;
  502. $main::EnlistSome = $main::FALSE;
  503. $main::EnlistFromProfile = $main::FALSE;
  504. $main::NewEnlist = $main::FALSE;
  505. $main::IncrEnlist = $main::FALSE;
  506. $main::Exclusions = $main::TRUE;
  507. $main::RestrictRoot = $main::FALSE;
  508. $main::EnlistAsOther = $main::FALSE;
  509. $main::Sync = $main::FALSE;
  510. $main::DefectWithPrejudice = $main::FALSE;
  511. $main::ToolsInRoot = $main::FALSE;
  512. $main::Quiet = $main::FALSE;
  513. $main::Logging = $main::FALSE;
  514. $main::CBMProjectField = 0; # change these if you change
  515. $main::CBMGroupField = 1; # the ordering of fields in
  516. $main::CBMServerPortField = 2; # file PROJECTS.<CODEBASE>
  517. $main::CBMDepotNameField = 3;
  518. $main::CBMProjectRootField = 4;
  519. $main::Profile = "";
  520. $main::OtherClient = "";
  521. $main::UserArgs = " ";
  522. $main::Branch = "";
  523. $main::SDXRoot = "";
  524. $main::SDCmd = "";
  525. $main::CodeBase = "";
  526. $main::SubmitComment = "";
  527. $main::ToolsProject = "";
  528. $main::ToolsPath = "";
  529. $main::ToolsProjectPath = "";
  530. @main::OtherDirs = ();
  531. @main::DefaultProjects = ();
  532. @main::PlatformProjects = ();
  533. @main::SomeProjects = ();
  534. @main::ProfileProjects = ();
  535. @main::InputForm = ();
  536. $main::MinusB = $main::FALSE;
  537. $main::MinusH = $main::FALSE;
  538. $main::MinusI = $main::FALSE;
  539. $main::MinusT = $main::FALSE;
  540. $main::MinusO = $main::FALSE;
  541. $main::MinusR = $main::FALSE;
  542. $main::MinusV = $main::FALSE;
  543. $main::MinusA = $main::FALSE;
  544. my $MinusC = $main::FALSE;
  545. my $MinusP = $main::FALSE;
  546. my $MinusX = $main::FALSE;
  547. #
  548. # check SDXROOT for correctness
  549. #
  550. !exists($ENV{SDXROOT}) and do
  551. {
  552. print "\n%SDXROOT% is not set.\n";
  553. $main::Usage = $main::TRUE;
  554. };
  555. #
  556. # don't allow illegal characters, or spaces at the beginning or end
  557. #
  558. # also don't allow '+' for now
  559. #
  560. my $root = $ENV{SDXROOT};
  561. (!$main::Usage and ($root =~ /[\/*?"<>|+]/ or $root =~ /[\t\s]+$/ or $root =~ /^[\t\s]+/)) and do
  562. {
  563. print "\n\%SDXROOT% contains bad or undesirable characters: '$root'.\n";
  564. $main::Usage = $main::TRUE;
  565. };
  566. !$main::Usage and ((substr($root,0,1) !~ /[A-Za-z]/) or (substr($root,1,1) !~ /:/) or (substr($root,2,1) !~ /\\/)) and do
  567. {
  568. print "\n%SDXROOT% badly formed: '$root'.\n";
  569. $main::Usage = $main::TRUE;
  570. };
  571. #
  572. # may need to bail and show usage
  573. #
  574. $main::Usage and return;
  575. #
  576. # otherwise set the root
  577. #
  578. $main::SDXRoot = $root;
  579. #
  580. # first arg is always the operation we want to do
  581. #
  582. # make sure it's not a flag
  583. # make sure it's a known cmd
  584. #
  585. if (($_[$ArgCounter] =~ /^-/) or ($_[$ArgCounter] =~ /^\//))
  586. {
  587. print "\nMissing command.\n";
  588. $main::Usage = $main::TRUE;
  589. return;
  590. }
  591. $main::SDCmd = $_[$ArgCounter];
  592. $main::SDCmd =~ tr/A-Z/a-z/;
  593. $ArgCounter++;
  594. #
  595. # return if no command or command not in list
  596. #
  597. if (!$main::SDCmd)
  598. {
  599. $main::Usage = $main::TRUE;
  600. return;
  601. }
  602. (!exists($main::SDCmds{$main::SDCmd})) and die("\nUnknown command '$main::SDCmd'. Try sdx -? for info.\n");
  603. #
  604. # determine which SDX command this is
  605. #
  606. # an "other" operation is assumed by default
  607. #
  608. # maybe show command list or usage
  609. #
  610. # if enlist/defect/repair, set flags and satisfy required
  611. # arguments later
  612. #
  613. ($main::SDCmd =~ /usage/) and $main::Usage = $main::TRUE;
  614. ($main::SDCmd =~ /commands/) and do
  615. {
  616. $main::Usage = $main::TRUE;
  617. $main::GetStarted = $main::FALSE;
  618. };
  619. $main::Usage and return;
  620. #
  621. # we have a valid command so any usage needed from this point
  622. # will be specific to main::SDCmd
  623. #
  624. $main::GetStarted = $main::FALSE;
  625. #
  626. # set flags for enlist/defect/repair
  627. #
  628. $main::SDCmd =~ /enlist/ and do
  629. {
  630. $main::Enlisting = $main::TRUE;
  631. $main::IncrEnlist = $main::TRUE;
  632. $main::EnlistSome = $main::TRUE;
  633. $main::OtherOp = $main::FALSE;
  634. };
  635. $main::SDCmd =~ /defect/ and do
  636. {
  637. $main::Defecting = $main::TRUE;
  638. $main::DefectSome = $main::TRUE;
  639. $main::OtherOp = $main::FALSE;
  640. };
  641. $main::SDCmd =~ /repair/ and do
  642. {
  643. $main::Repairing = $main::TRUE;
  644. $main::OtherOp = $main::FALSE;
  645. };
  646. my $ignore = "";
  647. #
  648. # Cycle through parameters
  649. #
  650. my $arg = "";
  651. my $subarg = "";
  652. while ($_[$ArgCounter])
  653. {
  654. #
  655. # if '-' or '/' is the first character in the arg then it's a flag
  656. #
  657. $arg = $_[$ArgCounter];
  658. if (($arg =~ /^-/) or ($arg =~ /^\//))
  659. {
  660. $ArgPosition = 0;
  661. CASE: while ($SubArg = substr $_[$ArgCounter], ++$ArgPosition)
  662. {
  663. $main::V2 and do
  664. {
  665. printf "subarg = '%s'\n", $SubArg;
  666. };
  667. #
  668. # -# <string> equals $SubmitComment
  669. #
  670. if ($SubArg =~ /^\#/)
  671. {
  672. #
  673. # the comment is from # to the end of the cmd string
  674. #
  675. if ($main::SDCmd eq "submit")
  676. {
  677. my $ac = $ArgCounter + 1;
  678. while ($_[$ac])
  679. {
  680. $main::SubmitComment .= "$_[$ac] ";
  681. $_[$ac] = "";
  682. $ac++;
  683. }
  684. #
  685. # set this for later
  686. #
  687. $main::MinusI = $main::TRUE;
  688. }
  689. next CASE;
  690. }
  691. #
  692. # -1 is verbose debugging
  693. #
  694. if ($SubArg =~ /^1/)
  695. {
  696. $main::V1 = $main::TRUE;
  697. next CASE;
  698. }
  699. #
  700. # -2 is very verbose
  701. #
  702. if ($SubArg =~ /^2/)
  703. {
  704. $main::V2 = $main::TRUE;
  705. next CASE;
  706. }
  707. #
  708. # -3 you get the picture
  709. #
  710. if ($SubArg =~ /^3/)
  711. {
  712. $main::V3 = $main::TRUE;
  713. next CASE;
  714. }
  715. #
  716. # -a equals All
  717. #
  718. # if enlisting set a flag for later
  719. # if defecting set defect flags
  720. # else pass on to the SD command
  721. #
  722. if ($SubArg =~ /^a/i)
  723. {
  724. if ($main::Enlisting)
  725. {
  726. $MinusA = $main::TRUE;
  727. }
  728. else
  729. {
  730. if ($main::Defecting)
  731. {
  732. $main::DefectAll = $main::TRUE;
  733. $main::DefectGroup = $main::FALSE;
  734. $main::DefectSome = $main::FALSE;
  735. # null out list in case we collected some projects already
  736. @main::SomeProjects = ();
  737. }
  738. else
  739. {
  740. if ($main::SDCmd eq "users" or $main::SDCmd eq "files" or $main::SDCmd eq "clients")
  741. {
  742. $main::MinusA = $main::TRUE;
  743. }
  744. else
  745. {
  746. SDX::AddUserArg($_[$ArgCounter]);
  747. }
  748. }
  749. }
  750. next CASE;
  751. }
  752. #
  753. # -b is build number
  754. #
  755. if ($SubArg =~ /^b/i)
  756. {
  757. if ($main::SDCmd eq "changes")
  758. {
  759. $main::MinusB = $main::TRUE;
  760. $ArgCounter++;
  761. if (!($main::BuildNumber = $_[$ArgCounter]))
  762. {
  763. print "\nMissing build number.\n";
  764. $main::Usage = $main::TRUE;
  765. }
  766. else
  767. {
  768. $_[$ArgCounter] = "";
  769. }
  770. }
  771. else
  772. {
  773. SDX::AddUserArg($_[$ArgCounter]);
  774. }
  775. next CASE;
  776. }
  777. #
  778. # -c is enlist clean
  779. #
  780. # if enlisting, set a flag for later
  781. # else pass on to the SD command
  782. #
  783. if ($SubArg =~ /^c/i)
  784. {
  785. if ($main::Enlisting)
  786. {
  787. $MinusC = $main::TRUE;
  788. }
  789. else
  790. {
  791. SDX::AddUserArg($_[$ArgCounter]);
  792. }
  793. next CASE;
  794. }
  795. #
  796. # if defecting, -f equals DefectWithPrejudice
  797. # else pass on to SD
  798. #
  799. if ($SubArg =~ /^f/i)
  800. {
  801. if ($main::Defecting)
  802. {
  803. $main::DefectWithPrejudice = $main::TRUE;
  804. }
  805. else
  806. {
  807. SDX::AddUserArg($_[$ArgCounter]);
  808. }
  809. next CASE;
  810. }
  811. #
  812. # -g equals Logging
  813. # the log file must be the next arg
  814. #
  815. if ($SubArg =~ /^g/i)
  816. {
  817. $ArgCounter++;
  818. if (!($main::Log = $_[$ArgCounter]))
  819. {
  820. print "\nMissing log file.\n";
  821. $main::Usage = $main::TRUE;
  822. }
  823. if (substr($main::Log,0,1) =~ /[\/-]/)
  824. {
  825. $main::Log !~ /\?/ and print "\nLog name '$main::Log' appears to be a command switch.\n";
  826. $main::Log = "";
  827. $main::Usage = $main::TRUE;
  828. }
  829. #
  830. # if we have a good log, set a flag and null out arg so it
  831. # doesn't end up in user args
  832. #
  833. !$main::Usage and ($main::Logging = $main::TRUE and $_[$ArgCounter] = "");
  834. next CASE;
  835. }
  836. #
  837. # -h -- set flag for later, on sync/flush only
  838. #
  839. if ($SubArg =~ /^h/i)
  840. {
  841. ($main::SDCmd =~ /sync|flush/) and $main::MinusH = $main::TRUE;
  842. next CASE;
  843. }
  844. #
  845. # -i -- read input form from cmd line, or
  846. # show integration changes if cmd is sync or flush, or
  847. # only rewrite SD.INIs if repairing
  848. #
  849. if ($SubArg =~ /^i/i)
  850. {
  851. $main::MinusI = $main::TRUE;
  852. ($main::SDCmd ne "sync" and $main::SDCmd ne "flush" and $main::SDCmd ne "repair" and $main::SDCmd ne "resolve") and @main::InputForm = <STDIN>;
  853. SDX::AddUserArg($_[$ArgCounter]);
  854. next CASE;
  855. }
  856. #
  857. # when enlisting, -m equals $MinimalTools
  858. #
  859. if ($SubArg =~ /^m/i)
  860. {
  861. if ($main::Enlisting)
  862. {
  863. $main::MinimalTools = $main::TRUE;
  864. }
  865. else
  866. {
  867. SDX::AddUserArg($_[$ArgCounter]);
  868. }
  869. next CASE;
  870. }
  871. #
  872. # -o -- set flag for later
  873. #
  874. if ($SubArg =~ /^o/i)
  875. {
  876. $main::MinusO = $main::TRUE;
  877. SDX::AddUserArg($_[$ArgCounter]);
  878. next CASE;
  879. }
  880. #
  881. # when enlisting or repairing, -p means read from profile
  882. # next arg must be path to the profile file
  883. #
  884. if ($SubArg =~ /^p/i)
  885. {
  886. if ($main::Enlisting or $main::Repairing)
  887. {
  888. $MinusP = $main::TRUE;
  889. $ArgCounter++;
  890. if (!($main::Profile = $_[$ArgCounter]))
  891. {
  892. print "\nMissing profile.\n";
  893. $main::Usage = $main::TRUE;
  894. }
  895. else
  896. {
  897. #
  898. # if we have a good Profile, set flags and null out arg so it
  899. # doesn't end up in user args
  900. #
  901. if (SDX::ReadProfile())
  902. {
  903. #
  904. # set flag for enlist or repair
  905. #
  906. $main::EnlistFromProfile = $main::TRUE;
  907. $main::Enlisting and do
  908. {
  909. $main::NewEnlist = $main::TRUE;
  910. $main::IncrEnlist = $main::FALSE;
  911. };
  912. $_[$ArgCounter] = "";
  913. }
  914. else
  915. {
  916. die("\n");
  917. }
  918. }
  919. }
  920. next CASE;
  921. }
  922. #
  923. # -q equals Quiet
  924. #
  925. if ($SubArg =~ /^q/i)
  926. {
  927. if ($main::SDCmd ne "diff2")
  928. {
  929. $main::Quiet = $main::TRUE;
  930. }
  931. else
  932. {
  933. SDX::AddUserArg($_[$ArgCounter]);
  934. }
  935. next CASE;
  936. }
  937. #
  938. # -r equals RI when submitting
  939. #
  940. if ($SubArg =~ /^r/i)
  941. {
  942. if ($main::SDCmd eq "submit")
  943. {
  944. $main::MinusR = $main::TRUE;
  945. $main::MinusT and do
  946. {
  947. printf "Already have -n, ignoring -%s.\n", $SubArg;
  948. $main::MinusR = $main::FALSE;
  949. };
  950. }
  951. else
  952. {
  953. SDX::AddUserArg($_[$ArgCounter]);
  954. }
  955. next CASE;
  956. }
  957. #
  958. # when enlisting, defecting or repairing, -s equals $Sync
  959. # else pass on
  960. #
  961. if ($SubArg =~ /^s/i)
  962. {
  963. if ($main::Enlisting || $main::Repairing || $main::Defecting)
  964. {
  965. $main::Sync = $main::TRUE;
  966. }
  967. else
  968. {
  969. SDX::AddUserArg($_[$ArgCounter]);
  970. }
  971. next CASE;
  972. }
  973. #
  974. # -t equals Integration when submitting
  975. #
  976. if ($SubArg =~ /^t/i)
  977. {
  978. if ($main::SDCmd eq "submit")
  979. {
  980. $main::MinusT = $main::TRUE;
  981. $main::MinusR and do
  982. {
  983. printf "Already have -r, ignoring -%s.\n", $SubArg;
  984. $main::MinusT = $main::FALSE;
  985. };
  986. }
  987. else
  988. {
  989. SDX::AddUserArg($_[$ArgCounter]);
  990. }
  991. next CASE;
  992. }
  993. #
  994. # -v equals Verbose
  995. #
  996. if ($SubArg =~ /^v/i)
  997. {
  998. $main::MinusV = $main::TRUE;
  999. #
  1000. # maybe pass -v on to SD
  1001. #
  1002. ($main::SDCmd eq "integrate" or $main::SDCmd eq "resolve") and do
  1003. {
  1004. SDX::AddUserArg($_[$ArgCounter]);
  1005. };
  1006. next CASE;
  1007. }
  1008. #
  1009. # when enlisting, -x turns off $Exclusions
  1010. # else pass on to SD
  1011. #
  1012. if ($SubArg =~ /^x/)
  1013. {
  1014. if ($main::Enlisting)
  1015. {
  1016. $MinusX = $main::TRUE;
  1017. }
  1018. else
  1019. {
  1020. SDX::AddUserArg($_[$ArgCounter]);
  1021. }
  1022. next CASE;
  1023. }
  1024. #
  1025. # -h or -? equals $Usage
  1026. #
  1027. if (($SubArg =~ /^h/i) or ($SubArg =~ /^\?/))
  1028. {
  1029. $main::Usage = $main::TRUE;
  1030. last CASE;
  1031. }
  1032. #
  1033. # add the switch to the user arg list
  1034. #
  1035. SDX::AddUserArg($_[$ArgCounter]);
  1036. last CASE;
  1037. }
  1038. }
  1039. else
  1040. {
  1041. #
  1042. # process non-switch args
  1043. #
  1044. #
  1045. # for general SD commands, add the arg to the user arg list
  1046. #
  1047. $main::OtherOp and do
  1048. {
  1049. SDX::AddUserArg($_[$ArgCounter]);
  1050. };
  1051. #
  1052. # if enlisting, arg is one of
  1053. # @client
  1054. # codebase and branch pair
  1055. # project name
  1056. #
  1057. $main::Enlisting and do
  1058. {
  1059. #
  1060. # first look for @<client>
  1061. #
  1062. if ((substr($_[$ArgCounter],0,1) =~ /@/) and !$main::EnlistAsOther)
  1063. {
  1064. $main::EnlistAsOther = $main::TRUE;
  1065. $main::NewEnlist = $main::TRUE;
  1066. $main::IncrEnlist = $main::FALSE;
  1067. $main::EnlistSome = $main::FALSE;
  1068. $main::OtherClient = substr($_[$ArgCounter],1,length($_[$ArgCounter]));
  1069. !$main::OtherClient and do
  1070. {
  1071. print "\nMissing client name after '\@'.\n";
  1072. $main::Usage = $main::TRUE;
  1073. };
  1074. $main::V2 and do
  1075. {
  1076. print "\nenlist as other = $main::EnlistAsOther\n";
  1077. print "other = '$main::OtherClient'\n";
  1078. print "new enlist = $main::NewEnlist\n";
  1079. print "incr enlist = $main::IncrEnlist\n";
  1080. };
  1081. }
  1082. else
  1083. {
  1084. #
  1085. # test for codebase if we don't have it already
  1086. #
  1087. # if arg is a codebase name (of the form PROJECTS.<codebase>) this is a new enlist
  1088. # assume the arg following is the branch name
  1089. #
  1090. if (!$main::CodeBase and SDX::VerifyCBMap($_[$ArgCounter]))
  1091. {
  1092. $main::NewEnlist = $main::TRUE;
  1093. $main::IncrEnlist = $main::FALSE;
  1094. $main::CodeBase = $_[$ArgCounter++];
  1095. $main::Branch = $_[$ArgCounter];
  1096. if ($main::Usage = SDX::VerifyCodeBaseAndBranch($main::CodeBase, $main::Branch))
  1097. {
  1098. $main::CodeBase = "";
  1099. $main::Branch = "";
  1100. }
  1101. $main::V2 and do
  1102. {
  1103. print "\nnew enlist = $main::NewEnlist\n";
  1104. print "incr enlist = $main::IncrEnlist\n";
  1105. print "codebase = '$main::CodeBase'\n";
  1106. print "branch = '$main::Branch'\n";
  1107. };
  1108. }
  1109. else
  1110. {
  1111. #
  1112. # arg is a project name
  1113. #
  1114. # maybe add to list
  1115. #
  1116. if (!$main::EnlistAll and !$main::EnlistAsOther and !$main::EnlistFromProfile)
  1117. {
  1118. #
  1119. # BUGBUG-2000/01/26-jeffmcd -- finish
  1120. #
  1121. # if arg is of the form project\path\path\path, break it apart
  1122. # and associate the path with the project so we can write it in the view later
  1123. # else
  1124. # it's just a project name
  1125. #
  1126. # if ($_[$ArgCounter] =~ /.+\\.+/)
  1127. # {
  1128. # my @fields = split(/\\/,$_[$ArgCounter]);
  1129. # my $project = @fields[0];
  1130. # push @main::SomeProjects, $project;
  1131. #
  1132. # shift @fields;
  1133. # my $subpath = "";
  1134. # foreach (@fields) { $subpath .= "$_\\"; }
  1135. # chop $subpath;
  1136. # print "'$subpath'\n";
  1137. # # load the hash -- use project as key
  1138. # push @$main::ProjectSubPaths{$project}, $subpath;
  1139. # }
  1140. # else
  1141. # {
  1142. push @main::SomeProjects, lc $_[$ArgCounter];
  1143. # }
  1144. }
  1145. }
  1146. }
  1147. };
  1148. #
  1149. # if incrementally defecting, arg is project to defect from
  1150. #
  1151. ($main::Defecting and !$main::DefectAll) and do
  1152. {
  1153. push @main::SomeProjects, lc $_[$ArgCounter];
  1154. };
  1155. #
  1156. # if repairing, current arg and the next are codebase and branch
  1157. #
  1158. $main::Repairing and do
  1159. {
  1160. #
  1161. # if codebase is null we need both values
  1162. # test the current arg to see if there's a codebase map for it, if so get the branch
  1163. #
  1164. !$main::CodeBase and do
  1165. {
  1166. SDX::VerifyCBMap($_[$ArgCounter]) and do
  1167. {
  1168. $main::CodeBase = $_[$ArgCounter++];
  1169. $main::Branch = $_[$ArgCounter];
  1170. if ($main::Usage = SDX::VerifyCodeBaseAndBranch($main::CodeBase, $main::Branch))
  1171. {
  1172. $main::CodeBase = "";
  1173. $main::Branch = "";
  1174. }
  1175. $main::V2 and do
  1176. {
  1177. print "\nrepairing, codebase = '$main::CodeBase'\n";
  1178. print "repairing, branch = '$main::Branch'\n";
  1179. };
  1180. };
  1181. };
  1182. #
  1183. # if we didn't use this arg as codebase, pass it on
  1184. #
  1185. (!$main::CodeBase) and SDX::AddUserArg($_[$ArgCounter]);
  1186. };
  1187. }
  1188. $ArgCounter++;
  1189. }
  1190. #
  1191. # maybe return for usage
  1192. #
  1193. $main::Usage and return;
  1194. #
  1195. # at this point all args have been accounted for
  1196. #
  1197. # figure out a couple things we couldn't earlier
  1198. #
  1199. #
  1200. # for a regular enlist-all, set some flags
  1201. #
  1202. ($MinusA and $main::Enlisting) and do
  1203. {
  1204. if (!$main::EnlistAsOther and !$main::EnlistFromProfile)
  1205. {
  1206. $main::EnlistAll = $main::TRUE;
  1207. $main::EnlistGroup = $main::FALSE;
  1208. $main::EnlistSome = $main::FALSE;
  1209. # null out list in case we collected some projects already
  1210. @main::SomeProjects = ();
  1211. }
  1212. else
  1213. {
  1214. $ignore .= " -a";
  1215. }
  1216. };
  1217. #
  1218. # enlist clean if not enlisting as another client
  1219. #
  1220. $MinusC and do
  1221. {
  1222. if (!$main::EnlistAsOther)
  1223. {
  1224. $main::EnlistClean = $main::TRUE;
  1225. }
  1226. else
  1227. {
  1228. $ignore .= " -c";
  1229. }
  1230. };
  1231. #
  1232. # enlisting as another client takes precedence over profiles
  1233. #
  1234. ($MinusP) and do
  1235. {
  1236. if ($main::EnlistAsOther)
  1237. {
  1238. $ignore .= " -p $main::Profile";
  1239. $main::EnlistFromProfile = $main::FALSE;
  1240. $main::Profile = "";
  1241. @main::SomeProjects = ();
  1242. }
  1243. else
  1244. {
  1245. #
  1246. # set flags
  1247. #
  1248. $main::NewEnlist = $main::TRUE;
  1249. $main::IncrEnlist = $main::FALSE;
  1250. $main::CodeBase = $main::ProfileCodeBase;
  1251. $main::Branch = $main::ProfileBranch;
  1252. push @main::SomeProjects, @main::ProfileProjects;
  1253. $main::V2 and do
  1254. {
  1255. $main::Repairing and print "\nrepairing from profile...\n";
  1256. print "\nnew enlist = $main::NewEnlist\n";
  1257. print "incr enlist = $main::IncrEnlist\n";
  1258. print "codebase = '$main::CodeBase'\n";
  1259. print "branch = '$main::Branch'\n";
  1260. print "some projects = '@main::SomeProjects'\n";
  1261. };
  1262. }
  1263. };
  1264. #
  1265. # ignore exclusions if not enlisting as another client
  1266. #
  1267. $MinusX and do
  1268. {
  1269. if (!$main::EnlistAsOther)
  1270. {
  1271. $main::Exclusions = $main::FALSE;
  1272. }
  1273. else
  1274. {
  1275. $ignore .= " -x";
  1276. }
  1277. };
  1278. #
  1279. # if we have args to ignore, say so
  1280. #
  1281. $main::EnlistAsOther and $ignore and printf "\nUsing client %s as a template, ignoring$ignore.\n", "\U$main::OtherClient";
  1282. $main::EnlistFromProfile and $ignore and print "\nUsing profile, ignoring$ignore and/or projects on command line.\n";
  1283. #
  1284. # do some early error checking so we can get usage if needed
  1285. #
  1286. $main::Enlisting and do
  1287. {
  1288. #
  1289. # make sure we're enlisting in either some or all projects
  1290. #
  1291. if (!$main::EnlistAsOther and !$main::EnlistSome and !$main::EnlistAll)
  1292. {
  1293. print "\nMissing projects to enlist, or -a.\n";
  1294. $main::Usage = $main::TRUE;
  1295. }
  1296. #
  1297. # if we're enlisting in only some projects and not as another client,
  1298. # the project list can't be empty
  1299. #
  1300. if ($main::EnlistSome and !$main::EnlistAsOther and ($#main::SomeProjects < 0))
  1301. {
  1302. print "\nMissing projects to enlist. Please specify projects or use -a for all.\n";
  1303. $main::Usage = $main::TRUE;
  1304. }
  1305. };
  1306. #
  1307. # same if defecting...
  1308. #
  1309. $main::Defecting and do
  1310. {
  1311. #
  1312. # make sure we're defecting in either some or all projects
  1313. #
  1314. if (!$main::DefectSome and !$main::DefectAll)
  1315. {
  1316. print "\nMissing projects to defect, or -a.\n";
  1317. $main::Usage = $main::TRUE;
  1318. }
  1319. #
  1320. # if we're defecting in only some projects, the project list
  1321. # can't be empty
  1322. #
  1323. if ($main::DefectSome and ($#main::SomeProjects < 0))
  1324. {
  1325. print "\nMissing projects to defect.\n";
  1326. $main::Usage = $main::TRUE;
  1327. }
  1328. };
  1329. #
  1330. # for now 'sdx branch' or 'sdx integrate' with no args is an error -- we don't want the UI popping up
  1331. # branch and integrate also requires args
  1332. #
  1333. (($main::SDCmd eq "branch" or $main::SDCmd eq "integrate") and $main::UserArgs =~ /^[\s]*$/) and do
  1334. {
  1335. print "\nMissing arguments to 'sdx $main::SDCmd'.\n";
  1336. $main::Usage = $main::TRUE;
  1337. };
  1338. #
  1339. # 'sdx opened -c' without 'default' is an error
  1340. #
  1341. (($main::SDCmd eq "opened") and ($main::UserArgs =~ /-c/ and $main::UserArgs !~ /-c default/)) and do
  1342. {
  1343. print "\n'sdx $main::SDCmd -c' requires 'default' as an argument.\n";
  1344. $main::Usage = $main::TRUE;
  1345. };
  1346. (($main::SDCmd eq "branch" or $main::SDCmd eq "change" or $main::SDCmd eq "user") and $main::UserArgs !~ /-o/) and do
  1347. {
  1348. print "\nOnly the -o switch is supported with 'sdx $main::SDCmd'.\n";
  1349. $main::Usage = $main::TRUE;
  1350. };
  1351. #
  1352. # don't allow "..." ".../*" ".../*.*" or their variations as arg to delete and edit
  1353. #
  1354. ($main::SDCmd eq "deletefile" or $main::SDCmd eq "editfile") and do
  1355. {
  1356. ($main::UserArgs =~ / \.\.\. |\.\.\.[\\\/]\*|\.\.\.[\\\/]+\*\.\* /) and do
  1357. {
  1358. my $ua = $main::UserArgs;
  1359. $ua =~ s/[\t\s]*//g;
  1360. print "\n'$ua' is not supported with 'sdx $main::SDCmd'.\n";
  1361. $main::Usage = $main::TRUE;
  1362. };
  1363. };
  1364. #
  1365. # only allow 'status' arg to sd admin
  1366. #
  1367. ($main::SDCmd eq "admin" and $main::UserArgs =~ / killthread | copyin | copyout | stop/) and do
  1368. {
  1369. print "\nOnly the 'status' command is supported with 'sdx admin'.\n";
  1370. $main::Usage = $main::TRUE;
  1371. };
  1372. #
  1373. # see if we need to check the format of (reverse) integration comments
  1374. #
  1375. # this helps sdx changes -b buildnum find I/RI events in the sd changes output
  1376. # and get build history
  1377. #
  1378. ($main::SDCmd eq "submit" and $main::SubmitComment) and SDX::VerifySubmitComment();
  1379. $main::V4 and do
  1380. {
  1381. print "\nparseargs: cmd line = '@_'\n\n";
  1382. printf "parseargs: op = %s\n", $main::SDCmd;
  1383. printf "parseargs: userargs = '%s'\n", $main::UserArgs;
  1384. printf "parseargs: e = %s\n", $main::Enlisting;
  1385. printf "parseargs: r = %s\n", $main::Repairing;
  1386. printf "parseargs: d = %s\n", $main::Defecting;
  1387. printf "parseargs: o = %s\n", $main::OtherOp;
  1388. printf "parseargs: ea = %s\n", $main::EnlistAll;
  1389. printf "parseargs: es = %s\n", $main::EnlistSome;
  1390. printf "parseargs: da = %s\n", $main::DefectAll;
  1391. printf "parseargs: ds = %s\n", $main::DefectSome;
  1392. print "parseargs: submitcomment = '$main::SubmitComment'\n";
  1393. printf "parseargs: logging = %s\n", $main::Logging;
  1394. printf "parseargs: logfile = '%s'\n", $main::Log;
  1395. printf "parseargs: enlistfromprofile = %s\n", $main::EnlistFromProfile;
  1396. printf "parseargs: profile = '%s'\n", $main::Profile;
  1397. printf "parseargs: newenlist = %s\n", $main::NewEnlist;
  1398. printf "parseargs: increnlist = %s\n", $main::IncrEnlist;
  1399. printf "parseargs: enlistasother = %s\n", $main::EnlistAsOther;
  1400. printf "parseargs: otherclient = '%s'\n", $main::OtherClient;
  1401. printf "parseargs: u = %s\n", $main::Usage;
  1402. printf "parseargs: v1 = %s\n", $main::V1;
  1403. printf "parseargs: v2 = %s\n", $main::V2;
  1404. printf "parseargs: quiet = %s\n", $main::Quiet;
  1405. printf "parseargs: mintools = %s\n", $main::MinimalTools;
  1406. printf "parseargs: sync = %s\n", $main::Sync;
  1407. printf "parseargs: defectwithprejudice = %s\n", $main::DefectWithPrejudice;
  1408. printf "parseargs: sdxroot = %s\n", $main::SDXRoot;
  1409. printf "parseargs: cb = %s\n", $main::CodeBase;
  1410. printf "parseargs: br = %s\n", $main::Branch;
  1411. (($main::MinusI and !$main::Repairing) and !$main::MinusH) and do
  1412. {
  1413. print "parseargs: input form on STDIN:\n";
  1414. foreach (@main::InputForm) { print "'$_'\n"; }
  1415. };
  1416. if ($main::EnlistSome or $main::DefectSome)
  1417. {
  1418. print "\nSome projects on cmd line:\n\n";
  1419. foreach $project (@main::SomeProjects)
  1420. {
  1421. printf "\t%s\n", $project;
  1422. }
  1423. print "\n";
  1424. }
  1425. print "\n";
  1426. };
  1427. }
  1428. # _____________________________________________________________________________
  1429. #
  1430. # AddUserArg
  1431. #
  1432. #
  1433. # Parameters:
  1434. #
  1435. # Output:
  1436. # _____________________________________________________________________________
  1437. sub AddUserArg
  1438. {
  1439. my $arg = $_[0];
  1440. #
  1441. # if the arg is a switch associated with bad cmds
  1442. # see if our cmd is in the list
  1443. #
  1444. ($arg =~ /^[-\/]/ and exists($main::BadCmds{$arg})) and do
  1445. {
  1446. foreach $cmd (@{$main::BadCmds{$arg}})
  1447. {
  1448. ($cmd eq $main::SDCmd) and die("\nThe 'sdx $main::SDCmd $arg' command is not supported.\n");
  1449. }
  1450. };
  1451. $main::V4 and do
  1452. {
  1453. print "adding '$arg ' to '$main::UserArgs'\n";
  1454. };
  1455. $main::UserArgs .= $arg . " ";
  1456. }
  1457. # _____________________________________________________________________________
  1458. #
  1459. # ReadSDMap
  1460. #
  1461. # reads project name and project root (relative path from %SDXROOT%) from
  1462. # %SDXROOT%\sd.map into a list for use by Defect() and OtherOp()
  1463. #
  1464. # Parameters:
  1465. #
  1466. # Output:
  1467. # populates $main::SDMapProjects list
  1468. # _____________________________________________________________________________
  1469. sub ReadSDMap
  1470. {
  1471. my $enlisting = ($_[0] eq "enlist");
  1472. my $defecting = ($_[0] eq "defect");
  1473. my $repairing = ($_[0] eq "repair");
  1474. my $otherop = ($_[0] eq "otherop");
  1475. my $init = ($_[1] eq "init");
  1476. my $line;
  1477. my $repairmsg = $main::FALSE;
  1478. my $enlistmsg = $main::FALSE;
  1479. my $nomapmsg = $main::FALSE;
  1480. my $nokeysmsg = $main::FALSE;
  1481. my $noprojmsg = $main::FALSE;
  1482. #
  1483. # need to re-init this here each time
  1484. #
  1485. @main::SDMapProjects = ();
  1486. $main::V3 and do
  1487. {
  1488. print "op = '$op'\n";
  1489. print "init = '$init'\n";
  1490. };
  1491. if (-e $main::SDMap)
  1492. {
  1493. open(SDMAP, "<$main::SDMap") or die("\nCan't open $main::SDMap for reading.\n");
  1494. while ($line = <SDMAP>)
  1495. {
  1496. #
  1497. # throw away comments, blank lines and certain non-project lines
  1498. #
  1499. $line =~ /^#|^[\t\s]*$/ and next;
  1500. #
  1501. # get the code base
  1502. #
  1503. if ($line =~ /^CODEBASE[\t\s]+/)
  1504. {
  1505. @fields = split(/[\t\s]*=[\t\s]*/, $line);
  1506. $main::SDMapCodeBase = "\U@fields[1]";
  1507. $main::SDMapCodeBase =~ s/[\t\s]*//g;
  1508. next;
  1509. }
  1510. #
  1511. # get the codebase type
  1512. #
  1513. if ($line =~ /^CODEBASETYPE/)
  1514. {
  1515. $main::SDMapCodeBaseType = (split(/[\t\s]*=[\t\s]*/, $line))[1];
  1516. chop $main::SDMapCodeBaseType;
  1517. next;
  1518. }
  1519. #
  1520. # get the branch
  1521. #
  1522. if ($line =~ /^BRANCH/)
  1523. {
  1524. $main::SDMapBranch = (split(/[\t\s]*=[\t\s]*/, $line))[1];
  1525. $main::SDMapBranch =~ s/[\t\s]*//g;
  1526. next;
  1527. }
  1528. #
  1529. # get the client
  1530. #
  1531. if ($line =~ /^CLIENT/)
  1532. {
  1533. $main::SDMapClient = (split(/[\t\s]*=[\t\s]*/, $line))[1];
  1534. $main::SDMapClient =~ s/[\t\s]*//g;
  1535. next;
  1536. }
  1537. #
  1538. # get the list of enlisted depots
  1539. #
  1540. if ($line =~ /^DEPOTS/)
  1541. {
  1542. my $fields = (split(/[\t\s]*=[\t\s]*/, $line))[1];
  1543. @main::SDMapDepots = split(/[\t\s]+/, $fields);
  1544. next;
  1545. }
  1546. #
  1547. # each line is of the form "project = projroot"
  1548. #
  1549. # throw away the '=' and push the project and root into the list
  1550. #
  1551. $line !~ /^(DEPOTS|CLIENT|BRANCH|CODEBASETYPE|CODEBASE)/ and do
  1552. {
  1553. chop $line;
  1554. $line =~ s/[\t\s]+//g;
  1555. @fields = split(/=/, $line);
  1556. push @main::SDMapProjects, [@fields];
  1557. };
  1558. }
  1559. close(SDMAP);
  1560. #
  1561. # if during init and no codebase type or depot list found,
  1562. # fix up the map quietly
  1563. #
  1564. ($init) and do
  1565. {
  1566. (!$main::SDMapCodeBaseType or !@main::SDMapDepots) and do SDX::FixSDMap();
  1567. #
  1568. # track the actively used depots
  1569. #
  1570. # incremental enlist and defect may add/remove depots to/from this list
  1571. #
  1572. @main::ActiveDepots = @main::SDMapDepots;
  1573. };
  1574. $main::V4 and do
  1575. {
  1576. print "\n";
  1577. foreach $p (@main::SDMapProjects)
  1578. {
  1579. printf "readsdm: project, root = %s, %s\n", @$p[0], @$p[1];
  1580. }
  1581. print "\n";
  1582. foreach $p (@main::SDMapDepots)
  1583. {
  1584. printf "readsdm: depot = %s\n", $p;
  1585. }
  1586. print "\nreadsdm: main::SDMapCodeBase = '$main::SDMapCodeBase'\n";
  1587. print "readsdm: main::SDMapBranch = '$main::SDMapBranch'\n";
  1588. print "readsdm: main::SDMapClient = '$main::SDMapClient'\n";
  1589. print "readsdm: main::SDMapCodeBaseType = '$main::SDMapCodeBaseType'\n";
  1590. };
  1591. #
  1592. # return code depends on what we're doing and when
  1593. #
  1594. if ($init)
  1595. {
  1596. #
  1597. # return if we have the keywords else fail with msg
  1598. #
  1599. $enlisting and do
  1600. {
  1601. $main::V4 and print "\nduring init, sd.map exists, enlisting\n";
  1602. $main::SDMapCodeBase and $main::SDMapBranch and $main::SDMapClient and return 1;
  1603. $nokeysmsg = $main::TRUE;
  1604. $repairmsg = $main::TRUE;
  1605. };
  1606. }
  1607. else
  1608. {
  1609. #
  1610. # all we care about in this case is the project list, b/c the map will
  1611. # be rewritten and any missing keywords restored
  1612. #
  1613. # fail silently if at all
  1614. #
  1615. $enlisting and do
  1616. {
  1617. $main::V4 and print "\nduring EDR, sd.map exists, enlisting\n";
  1618. @main::SDMapProjects and return 1;
  1619. };
  1620. }
  1621. #
  1622. # always return successfully when repairing, so we can continue and
  1623. # rewrite any missing lines from the map
  1624. #
  1625. $repairing and do
  1626. {
  1627. $main::V4 and print "\nduring EDR, sd.map exists, repairing\n";
  1628. return 1;
  1629. };
  1630. #
  1631. #
  1632. #
  1633. ($defecting or $otherop) and do
  1634. {
  1635. $main::V4 and print "\nduring EDR, sd.map exists, defecting or otherop\n";
  1636. if ($main::SDMapCodeBase and $main::SDMapBranch and $main::SDMapClient)
  1637. {
  1638. @main::SDMapProjects and return 1;
  1639. $noprojmsg = $main::TRUE;
  1640. }
  1641. else
  1642. {
  1643. $nokeysmsg = $main::TRUE;
  1644. }
  1645. $repairmsg = $main::TRUE;
  1646. };
  1647. #
  1648. # print error msgs
  1649. #
  1650. $nokeysmsg and do
  1651. {
  1652. printf "\n%s is missing one or more required keywords.\n", "\U$main::SDMap";
  1653. };
  1654. $noprojmsg and do
  1655. {
  1656. print "\nNo projects found in \U$main::SDMap.\n";
  1657. };
  1658. $repairmsg and do
  1659. {
  1660. 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>";
  1661. };
  1662. }
  1663. else
  1664. {
  1665. #
  1666. # SD.MAP is missing
  1667. #
  1668. if ($init)
  1669. {
  1670. #
  1671. # assume this is an incremental enlist
  1672. #
  1673. ($enlisting and !$main::NewEnlist) and do
  1674. {
  1675. $nomapmsg = $main::TRUE;
  1676. $enlistmsg = $main::TRUE;
  1677. };
  1678. ($repairing or $defecting or $otherop) and do
  1679. {
  1680. $nomapmsg = $main::TRUE;
  1681. !$repairing and $repairmsg = $main::TRUE;
  1682. };
  1683. }
  1684. else
  1685. {
  1686. $enlisting and do
  1687. {
  1688. $main::V2 and print "\nduring EDR, no sd.map, enlisting\n";
  1689. };
  1690. $repairing and do
  1691. {
  1692. $main::V2 and print "\nduring EDR, no sd.map, repairing\n";
  1693. };
  1694. $defecting and do
  1695. {
  1696. $main::V2 and print "\nduring EDR, no sd.map, defecting\n";
  1697. };
  1698. $otherop and do
  1699. {
  1700. $main::V2 and print "\nduring EDR, no sd.map, otherop\n";
  1701. };
  1702. };
  1703. #
  1704. # print error msgs specific to missing SD.MAP cases
  1705. #
  1706. $nomapmsg and printf "\nCan't find %s to get enlistment information.\n", "\U$main::SDMap";
  1707. $enlistmsg and !$repairmsg and do
  1708. {
  1709. print "\nIf this is a new enlistment please run 'sdx enlist <codebase> <branch>' to\n";
  1710. print "specify the set of sources and the branch you want to enlist in.\n";
  1711. print "\nIf you are adding projects to an existing enlistment, the SD.MAP at\n";
  1712. printf "%s is missing. Run 'sdx repair <codebase> <branch>' to restore\n", "\U$main::SDXRoot";
  1713. print "it, then rerun this command.\n";
  1714. };
  1715. $repairmsg and !$enlistmsg and do
  1716. {
  1717. print "\nVerify that \%SDXROOT\% is set correctly, and that ";
  1718. printf "%s contains\n", "\U$main::SDXRoot";
  1719. printf "a valid enlistment. If it does, run 'sdx repair %s %s'\n", ($main::CodeBase ? $main::CodeBase : "<codebase>"), ($main::Branch ? $main::Branch : "<branch>");
  1720. print "to restore SD.MAP, then rerun this command.\n";
  1721. };
  1722. ($repairmsg or $enlistmsg) and print "\nRun 'sdx repair -?' to see what repairing does to your enlistment.\n";
  1723. }
  1724. return 0;
  1725. }
  1726. # _____________________________________________________________________________
  1727. #
  1728. # FixSDMap
  1729. #
  1730. # silently adds missing keywords to the user's SD.MAP
  1731. #
  1732. # Parameters:
  1733. #
  1734. # Output:
  1735. # _____________________________________________________________________________
  1736. sub FixSDMap
  1737. {
  1738. #
  1739. # if no list of enlisted depots, figure it out and append it to the map
  1740. #
  1741. !@main::SDMapDepots and do
  1742. {
  1743. #
  1744. # figure out the list of active depots
  1745. #
  1746. SDX::OtherOp("enumdepots","");
  1747. #
  1748. # append
  1749. #
  1750. system "attrib -R -H -S $main::SDMap >nul 2>&1";
  1751. open(SDMAP, ">>$main::SDMap") or die("\nCan't append $main::SDMap.\n");
  1752. print SDMAP "\n";
  1753. SDX::WriteSDMapDepots(\@main::SDMapDepots, *SDMAP);
  1754. close SDMAP;
  1755. system "attrib +R +H +S $main::SDMap >nul 2>&1";
  1756. };
  1757. #
  1758. # same for the codebase type
  1759. #
  1760. !$main::SDMapCodeBaseType and do
  1761. {
  1762. #
  1763. # need to act as though we were enlisting to get enough information
  1764. # to determine the type
  1765. #
  1766. $main::CodeBase = $main::SDMapCodeBase;
  1767. if (SDX::VerifyCBMap($main::CodeBase))
  1768. {
  1769. SDX::ReadCodeBaseMap();
  1770. $main::SDMapCodeBaseType = $main::CodeBaseType;
  1771. #
  1772. # throw away results of the map read so we don't get duplicates
  1773. #
  1774. $main::ToolsProject = "";
  1775. $main::ToolsPath = "";
  1776. $main::ToolsProjectPath = "";
  1777. }
  1778. else
  1779. {
  1780. print "\n\nError fixing SD.MAP: can't find codebase map $main::CodeBaseMap.\n";
  1781. die("\nContact the SDX alias.\n");
  1782. }
  1783. #
  1784. # append
  1785. #
  1786. system "attrib -R -H -S $main::SDMap >nul 2>&1";
  1787. open(SDMAP, ">>$main::SDMap") or die("\nCan't append $main::SDMap.\n");
  1788. SDX::WriteSDMapCodeBaseType($main::SDMapCodeBaseType, *SDMAP);
  1789. close SDMAP;
  1790. system "attrib +R +H +S $main::SDMap >nul 2>&1";
  1791. };
  1792. }
  1793. # _____________________________________________________________________________
  1794. #
  1795. # EnumDepots
  1796. #
  1797. # called by FixSDMap by OtherOp to walk the project roots and find SDPORT
  1798. # values
  1799. #
  1800. # Parameters:
  1801. #
  1802. # Output:
  1803. # populates @main::SDMapDepots for writing to SD.MAP
  1804. # _____________________________________________________________________________
  1805. sub EnumDepots
  1806. {
  1807. my $userargs = $_[0];
  1808. my $project = $_[1];
  1809. my $sdini = $_[2];
  1810. my $sp;
  1811. $main::V4 and do
  1812. {
  1813. print "\n\n\nuserargs = '$userargs'\n";
  1814. print "project = '$project'\n";
  1815. };
  1816. #
  1817. # get server:port
  1818. #
  1819. open(INI, "< $sdini") or die("\nCan't read SD.INI.\n");
  1820. while (<INI>)
  1821. {
  1822. /^SDPORT/ and do
  1823. {
  1824. $sp = (split(/=/,$_))[1];
  1825. chop $sp;
  1826. };
  1827. }
  1828. close(INI);
  1829. #
  1830. # add to hash if unique
  1831. #
  1832. unless ($main::DepotsSeen{$sp})
  1833. {
  1834. $main::DepotsSeen{$sp} = 1;
  1835. push @main::SDMapDepots, $sp;
  1836. }
  1837. }
  1838. # _____________________________________________________________________________
  1839. #
  1840. # ListProjects
  1841. #
  1842. # Parameters:
  1843. #
  1844. # Output:
  1845. # _____________________________________________________________________________
  1846. sub ListProjects
  1847. {
  1848. my $userargs = $_[0];
  1849. my $project = $_[1];
  1850. $main::V2 and do
  1851. {
  1852. print "\n\n\nuserargs = '$userargs'\n";
  1853. print "project = '$project'\n";
  1854. };
  1855. SDX::PrintCmd($header, 0);
  1856. for $p (@main::SDMapProjects)
  1857. {
  1858. (@$p[0] eq $project) and print "\n$main::SDXRoot\\@$p[1]\n";
  1859. }
  1860. }
  1861. # _____________________________________________________________________________
  1862. #
  1863. # Enlist
  1864. #
  1865. # Parameters:
  1866. #
  1867. # Output:
  1868. # _____________________________________________________________________________
  1869. sub Enlist
  1870. {
  1871. #
  1872. # munge the codebase map to create project, depot and group lists
  1873. # and figure out what the user wants to enlist in
  1874. #
  1875. if (SDX::InitForEnlist())
  1876. {
  1877. #
  1878. # for each depot we're enlisting in
  1879. # get the list of projects in this depot
  1880. # create/update the client view
  1881. # create/update the SD.MAP
  1882. # write the SD.INIs
  1883. #
  1884. foreach $depot (@main::EnlistDepots)
  1885. {
  1886. $serverport = @$depot[0];
  1887. $main::V3 and print "\n$serverport\n";
  1888. #
  1889. # from the list of all projects to enlist in, create a list of
  1890. # projects found in the current depot only
  1891. #
  1892. @main::ProjectsInThisDepot = ();
  1893. foreach $project (@main::EnlistProjects)
  1894. {
  1895. if ($serverport eq @$project[$main::CBMServerPortField])
  1896. {
  1897. push @main::ProjectsInThisDepot, [@{$project}];
  1898. $main::V3 and print "\t@$project\n";
  1899. }
  1900. }
  1901. print "\n";
  1902. #
  1903. # create or update the client view
  1904. #
  1905. SDX::EnlistProjects($depot, "enlist");
  1906. #
  1907. # upon registering the first client, release the mutex we
  1908. # took ownership of in MakeUniqueClient() so other enlists
  1909. # can continue
  1910. #
  1911. $main::HaveMutex and do
  1912. {
  1913. $main::HaveMutex = $main::FALSE;
  1914. $main::Mutex->release;
  1915. };
  1916. #
  1917. # create/update %SDXROOT%\SD.MAP
  1918. #
  1919. SDX::UpdateSDMap("enlist");
  1920. #
  1921. # create/update %SDXROOT%\SD.MAP
  1922. #
  1923. SDX::UpdateSDINIs("enlist");
  1924. }
  1925. #
  1926. # finish it off
  1927. #
  1928. SDX::FinishEnlist();
  1929. #
  1930. # success
  1931. #
  1932. return 0;
  1933. }
  1934. else
  1935. {
  1936. printf "\nSDX had errors reading the file PROJECTS.%s or in constructing the list of\n", "\U$main::CodeBase";
  1937. print "projects and depots for enlisting.\n";
  1938. #
  1939. # failure
  1940. #
  1941. return 1;
  1942. }
  1943. }
  1944. # _____________________________________________________________________________
  1945. #
  1946. # InitForEnlist
  1947. #
  1948. # Parameters:
  1949. # Command Line Arguments
  1950. #
  1951. # Output:
  1952. # returns 1 if successful, 0 otherwise
  1953. # _____________________________________________________________________________
  1954. sub InitForEnlist
  1955. {
  1956. #
  1957. # do the common init
  1958. #
  1959. SDX::InitForEDR("enlist");
  1960. #
  1961. # set the branch flag
  1962. #
  1963. # one of the following is true about $main::Branch
  1964. # - it matches $main::MasterBranch, in which case we're enlisting in the
  1965. # main sources for all projects for this code base
  1966. # - it matches one of the group build lab branch names, in which case we're
  1967. # enlisting in that lab's branched sources for all projects
  1968. # - it matches some other root-level branch defined by a developer or
  1969. # private lab
  1970. #
  1971. if ($main::Branch eq $main::MasterBranch)
  1972. {
  1973. $main::EnlistingMainBranch = $main::TRUE;
  1974. }
  1975. else
  1976. {
  1977. foreach $br (@main::GroupBranches)
  1978. {
  1979. if ($main::Branch eq $br)
  1980. {
  1981. $main::EnlistingGroupBranch = $main::TRUE;
  1982. last;
  1983. }
  1984. }
  1985. }
  1986. if (!$main::EnlistingMainBranch && !$main::EnlistingGroupBranch)
  1987. {
  1988. $main::EnlistingPrivateBranch = $main::TRUE;
  1989. }
  1990. # more error checking:
  1991. # - branch name can't be a project name
  1992. # - must be enlisting in all or some projects
  1993. # - if only some, project list can't be null
  1994. #
  1995. # verify that the branch the user gave us is not one of the projects
  1996. # in the codebase map. if so, they probably forgot to specify the
  1997. # branch name on the cmd line
  1998. #
  1999. foreach $project (@main::AllProjects)
  2000. {
  2001. ($main::Branch eq @$project[$main::CBMProjectField]) and die("\nBranch name '$main::Branch' appears to be a project.\n");
  2002. }
  2003. #
  2004. # from the lists of all projects, groups and depots, create the lists
  2005. # of just those we'll enlist in
  2006. #
  2007. SDX::MakeTargetLists("enlist");
  2008. #
  2009. # see if we need to use a unique client name
  2010. #
  2011. if ($main::NewEnlist)
  2012. {
  2013. $main::SDClient = SDX::MakeUniqueClient();
  2014. }
  2015. else
  2016. {
  2017. SDX::VerifyAccess();
  2018. }
  2019. #
  2020. # if we have depots and projects to enlist in, continue
  2021. # else politely error-out
  2022. #
  2023. if (@main::EnlistDepots && @main::EnlistProjects)
  2024. {
  2025. if ($main::EnlistAsOther)
  2026. {
  2027. printf "\n\n\nThis script will enlist you in the %s sources using these settings:\n\n", "\U$main::CodeBase";
  2028. }
  2029. else
  2030. {
  2031. printf "\n\n\nThis script will %s in the %s sources", $main::NewEnlist ? "enlist you" : "add projects to your enlistment", "\U$main::CodeBase";
  2032. printf "%susing these settings:\n\n", $main::NewEnlist ? " " : "\n";
  2033. }
  2034. printf "\tRoot directory:\t\t%s\n", "\U$main::SDXRoot";
  2035. printf "\tBranch:\t\t\t%s\n", "\U$main::Branch";
  2036. printf "\tSD client name:\t\t%s\n", $main::SDClient;
  2037. printf "\tSD user name:\t\t%s\n", $main::SDDomainUser;
  2038. $main::EnlistAsOther and printf "\tClient template:\t%s\n", "\U$main::OtherClient";
  2039. #
  2040. # print the projects we're going to enlist in
  2041. #
  2042. $np = $#main::EnlistProjects+1;
  2043. printf "\n\tEnlisting in %s project%s...\n\n", $np, $np > 1 ? "s" : "";
  2044. foreach $project (@main::EnlistProjects)
  2045. {
  2046. printf "\t %s\n", @$project[$main::CBMProjectField];
  2047. }
  2048. #
  2049. # print the depots we're going to enlist in
  2050. #
  2051. $nd = $#main::EnlistDepots+1;
  2052. printf "\n\t...across %s depot%s:\n\n", $nd, $nd > 1 ? "s" : "";
  2053. foreach $depot (@main::EnlistDepots)
  2054. {
  2055. printf "\t %s\n", @$depot[0];
  2056. }
  2057. print "\n\nIF YOU ARE NOT READY TO ENLIST WITH THESE SETTINGS, HIT CTRL-BREAK NOW.\n";
  2058. print " ==================\n\n\n";
  2059. print "Otherwise,\n\n";
  2060. !$main::Quiet and system "pause";
  2061. print "\n\n";
  2062. #
  2063. # warn user if the branch they want doesn't exist
  2064. #
  2065. ###
  2066. ### SDX::VerifyBranch("enlist", $nd) and print "\nWarning: branch '$main::Branch' does not exist in one or more depots\n";
  2067. #
  2068. # if enlisting as another client, make sure the new client we want to create
  2069. # doesn't already exist
  2070. #
  2071. $main::EnlistAsOther and SDX::VerifyClient($nd);
  2072. #
  2073. # add some or all of the depots we're about to enlist in to
  2074. # the active list so they show up in SD.MAP later
  2075. #
  2076. SDX::UpdateActiveDepots("enlist", "");
  2077. $main::V4 and do
  2078. {
  2079. printf "\n";
  2080. printf "initforenlist: cb=%s\n", $main::CodeBase;
  2081. printf "initforenlist: cbm=%s\n", $main::CodeBaseMap;
  2082. printf "initforenlist: mb=%s\n", $main::MasterBranch;
  2083. printf "initforenlist: cv=%s\n", $main::ClientView;
  2084. printf "\n";
  2085. };
  2086. return 1;
  2087. }
  2088. else
  2089. {
  2090. !@main::EnlistProjects and print "\nNo projects found. Unable to enlist.\n" and return 0;
  2091. !@main::EnlistDepots and print "\nNo depots found. Unable to enlist.\n" and return 0;
  2092. }
  2093. }
  2094. # _____________________________________________________________________________
  2095. #
  2096. # UpdateActiveDepots
  2097. #
  2098. # Add or remove server:port values to active depot list, depending on
  2099. # operation
  2100. #
  2101. # Parameters:
  2102. #
  2103. # Output:
  2104. # _____________________________________________________________________________
  2105. sub UpdateActiveDepots
  2106. {
  2107. my $op = $_[0];
  2108. my $sp = $_[1];
  2109. my $enlisting = ($op eq "enlist");
  2110. my $defecting = ($op eq "defect");
  2111. ($enlisting) and do
  2112. {
  2113. #
  2114. # on a clean enlist the list of active depots is
  2115. # those the user will enlist in
  2116. #
  2117. # active depot list is written to SD.MAP after enlisting
  2118. #
  2119. ($main::NewEnlist) and do
  2120. {
  2121. my @unsorted = ();
  2122. for $depot (@main::EnlistDepots)
  2123. {
  2124. push @unsorted, @$depot[0];
  2125. }
  2126. #
  2127. # want this sorted
  2128. #
  2129. @main::ActiveDepots = SDX::SortDepots(\@unsorted);
  2130. };
  2131. #
  2132. # on an incremental enlist, add new depots only
  2133. #
  2134. ($main::IncrEnlist) and do
  2135. {
  2136. my %hash = ();
  2137. for $depot (@main::ActiveDepots)
  2138. {
  2139. $hash{$depot} = 1;
  2140. }
  2141. $main::V3 and do
  2142. {
  2143. print "\nhash:\n";
  2144. while (($k,$v) = each %hash)
  2145. {
  2146. printf " %-50s\t%s\n", $k, $v;
  2147. }
  2148. };
  2149. for $depot (@main::EnlistDepots)
  2150. {
  2151. my $sp = @$depot[0];
  2152. ($hash{$sp} != 1) and do
  2153. {
  2154. push @main::ActiveDepots, $sp;
  2155. };
  2156. }
  2157. @main::ActiveDepots = SDX::SortDepots(\@main::ActiveDepots);
  2158. };
  2159. };
  2160. #
  2161. # null out dead server:port in active list
  2162. #
  2163. ($defecting) and do
  2164. {
  2165. $main::V3 and do
  2166. {
  2167. print "\nbefore:\n";
  2168. for $d (@main::ActiveDepots)
  2169. {
  2170. print " '$d'\n";
  2171. }
  2172. };
  2173. grep {s/$sp//g} @main::ActiveDepots;
  2174. $main::V3 and do
  2175. {
  2176. print "\nafter:\n";
  2177. for $d (@main::ActiveDepots)
  2178. {
  2179. print " '$d'\n";
  2180. }
  2181. };
  2182. };
  2183. }
  2184. # _____________________________________________________________________________
  2185. #
  2186. # EnlistProjects
  2187. #
  2188. # Parameters:
  2189. #
  2190. # Output:
  2191. # _____________________________________________________________________________
  2192. sub EnlistProjects
  2193. {
  2194. $depot = $_[0];
  2195. $op = $_[1];
  2196. $serverport = @$depot[0];
  2197. if ($main::EnlistAsOther)
  2198. {
  2199. #
  2200. # register a new view using another client as a template
  2201. #
  2202. my $desc = 0;
  2203. my $pr = 0;
  2204. unlink $main::ClientView;
  2205. #
  2206. # Root: field for client view depends on depot type
  2207. #
  2208. # for type 1 (1 project/depot), root includes project name
  2209. # for type 2 (N projects/depot), root is just main::SDXRoot
  2210. #
  2211. # root is at least SDXRoot in either case
  2212. #
  2213. $root = $main::SDXRoot;
  2214. (@{$main::DepotType{$serverport}}[0] == 1) and $root = SDX::Type1Root($root);
  2215. #
  2216. # dump the other client into a list
  2217. #
  2218. @lines = `sd.exe -p $serverport client -o $main::OtherClient`;
  2219. $main::V3 and print "otherclient = '@lines'\n\n";
  2220. #
  2221. # munge the other's view to create a template
  2222. #
  2223. open(CLIENTVIEW, ">$main::ClientView") or die("\nCan't open $main::ClientView for writing.\n");
  2224. #
  2225. # if OtherClient is a unique name, double up on the '\' so
  2226. # the s///gi works correctly
  2227. #
  2228. my $other = $main::OtherClient;
  2229. $other =~ s/\\/\\\\/g;
  2230. #
  2231. # transmogrify the client spec lines
  2232. #
  2233. foreach $line (@lines)
  2234. {
  2235. #
  2236. # if the most recent line was the description, the current line is its text
  2237. #
  2238. $desc and do
  2239. {
  2240. $line =~ s/^[\t\s]+.+/\tCreated by $main::SDDomainUser./g;
  2241. print CLIENTVIEW "$line";
  2242. $desc = 0;
  2243. next;
  2244. };
  2245. # throw away comments and certain other lines
  2246. $line =~ /(Update|Access):|^#/ and next;
  2247. # replace Client: with our client
  2248. $line =~ s/^Client:[\t\s]*.+/Client: $main::SDClient/g;
  2249. # replace owner name with our user name
  2250. $line =~ s/^Owner:[\t\s]*.+/Owner: $main::SDDomainUser/g;
  2251. # found the desc line, set a flag and replace it next time through
  2252. $line =~ /^Description:/ and $desc = 1;
  2253. # replace the old root with ours
  2254. $line =~ s/^Root:[\t\s]*.+/Root: $root/g;
  2255. # replace other client name in view lines with ours
  2256. $line =~ s/$other/$main::SDClient/gi;
  2257. print CLIENTVIEW "$line";
  2258. }
  2259. close(CLIENTVIEW);
  2260. $main::V2 and do
  2261. {
  2262. print "==========\n";
  2263. system "type $main::ClientView";
  2264. print "==========\n";
  2265. };
  2266. }
  2267. else
  2268. {
  2269. #
  2270. # create/update the view spec
  2271. #
  2272. SDX::CreateView($depot, $op);
  2273. }
  2274. #
  2275. # register the new/updated view
  2276. #
  2277. system "sd.exe -p $serverport client -i < $main::ClientView";
  2278. }
  2279. # _____________________________________________________________________________
  2280. #
  2281. # FinishEnlist
  2282. #
  2283. # Finish up by:
  2284. # maybe syncing projects for the user
  2285. # generating SDINIT and alias files
  2286. # syncing the tools dir
  2287. # syncing any other dirs specified by the codebase map
  2288. # providing friendly verbage
  2289. #
  2290. # Parameters:
  2291. # none
  2292. #
  2293. # Output:
  2294. # _____________________________________________________________________________
  2295. sub FinishEnlist
  2296. {
  2297. #
  2298. # cleanup
  2299. #
  2300. unlink $main::ClientView;
  2301. #
  2302. # maybe unghost
  2303. #
  2304. $main::Sync and SDX::SyncFiles("enlist", $main::Null, $main::Null);
  2305. #
  2306. # give the user some direction on how to get started
  2307. #
  2308. # if the codebase map identified a tools dir, point them to that
  2309. # otherwise copy down the tools for them
  2310. #
  2311. #
  2312. # give the user the SD/SDX tools, batch files for aliases and SDX commands
  2313. #
  2314. SDX::ToolsEtc("enlist");
  2315. #
  2316. # also sync any OtherDirs at this time
  2317. #
  2318. @main::OtherDirs and SDX::SyncOtherDirs("enlist");
  2319. #
  2320. # if NT, addfile a default \developer\<username>\setenv.cmd
  2321. # not there yet
  2322. #
  2323. ("\U$main::CodeBase" eq "NT") and SDX::WriteDefaultSetEnv();
  2324. #
  2325. # verbage for a succesful enlist
  2326. #
  2327. print "\nDone.\n";
  2328. $main::NewEnlist and do
  2329. {
  2330. $main::SDXRoot =~ tr/a-z/A-Z/;
  2331. $main::CodeBase =~ tr/a-z/A-Z/;
  2332. $sdtools = $main::SDXRoot . "\\sdtools";
  2333. print "\n\nThe directory $main::SDXRoot is now enlisted in the $main::CodeBase sources.\n";
  2334. print "\nThese SDX files were placed in your enlistment:\n";
  2335. if ($main::ToolsProject)
  2336. {
  2337. print "\n $main::SDXRoot\n";
  2338. printf "\t%-24smap to project roots and SD.INIs\n", "SD.MAP";
  2339. print "\n \U$main::ToolsProjectPath\n";
  2340. printf "\t%-24saliases for logging SDX output\n", "ALIAS.SDX";
  2341. printf "\t%-24saliases for navigating your enlistment\n", "ALIAS." . $main::CodeBase;
  2342. $main::CodeBaseMapFile =~ tr/a-z/A-Z/;
  2343. printf "\t%-24scodebase map for future enlist/defect/repair\n", $main::CodeBaseMapFile;
  2344. printf "\t%-24ssets default Source Depot vars and aliases\n", "SDINIT.CMD";
  2345. printf "\t%-24sscripts for cross-depot commands\n", "SDX.\*";
  2346. if (
  2347. "\U$main::CodeBase" eq "NT" or
  2348. "\U$main::CodeBase" eq "NTSDK" or
  2349. ("\U$main::CodeBase" eq "NTTEST" and !$main::RestrictRoot) or
  2350. "\U$main::CodeBase" eq "NT.INTL" or
  2351. "\U$main::CodeBase" eq "MPC" or
  2352. "\U$main::CodeBase" eq "NGWS" or
  2353. "\U$main::CodeBase" eq "MGMT" or
  2354. "\U$main::CodeBase" eq "MOM" or
  2355. "\U$main::CodeBase" eq "PDDEPOT" or
  2356. "\U$main::CodeBase" eq "WINMEDIA" or
  2357. "\U$main::CodeBase" eq "WINSS"
  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. my $crlf = $main::FALSE;
  5881. $serverport = @$depot[0];
  5882. $depotname = @$depot[1];
  5883. @main::tmpView = ();
  5884. @main::FinalView = ();
  5885. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in CreateView().\n");
  5886. unlink $main::ClientView;
  5887. #
  5888. # write the default view lines for this depot and project(s)
  5889. #
  5890. SDX::WriteDefaultView($serverport, $depotname);
  5891. #
  5892. # if we're doing a clean enlist or the client doesn't already exist,
  5893. # use the default view
  5894. # else merge the default view with the existing view
  5895. #
  5896. if ($main::CleanEnlist or !SDX::ClientExists($serverport, $main::SDClient))
  5897. {
  5898. #
  5899. # Root: field for client view depends on depot type
  5900. #
  5901. # for type 1 (1 project/depot), root includes project name
  5902. # for type 2 (N projects/depot), root is just main::SDXRoot
  5903. #
  5904. # root is at least SDXRoot in either case
  5905. #
  5906. $root = $main::SDXRoot;
  5907. (@{$main::DepotType{$serverport}}[0] == 1) and $root = SDX::Type1Root($root);
  5908. #
  5909. # files in root project in NT are clobberable
  5910. #
  5911. # BUGBUG-2000/5/12-jeffmcd -- this should be an option in the codebase map -- ClobberRoot = 1 or 0
  5912. # 2002/9/5 -jeremyd -- the whole options line should be configurable and fall back to server defaults
  5913. #
  5914. if ("\U$main::CodeBase" eq "NT")
  5915. {
  5916. $project = @main::ProjectsInThisDepot[0];
  5917. $clobber = ("\L@$project[$main::CBMProjectField]" eq "root");
  5918. }
  5919. #
  5920. # SQL SD server is setup as crlf
  5921. #
  5922. if ("\l$serverport" eq "sqldepot.sys-ntgroup.ntdev.microsoft.com:1666")
  5923. {
  5924. $crlf = $main::TRUE;
  5925. }
  5926. #
  5927. # write default view header
  5928. #
  5929. open(CLIENTVIEW, ">$main::ClientView") or die("\nCan't open $main::ClientView for writing.\n");
  5930. printf CLIENTVIEW "Client: %s\n\n", $main::SDClient;
  5931. printf CLIENTVIEW "Owner: %s\n\n", $main::SDDomainUser;
  5932. printf CLIENTVIEW "Description:\n Created by %s.\n\n", $main::SDDomainUser;
  5933. printf CLIENTVIEW "Root: %s\n\n", $root;
  5934. printf CLIENTVIEW "Options: noallwrite %sclobber nocompress %scrlf locked nomodtime\n\n", $clobber ? "" : "no", $crlf ? "" : "no";
  5935. printf CLIENTVIEW "View:\n";
  5936. #
  5937. # append the default view
  5938. #
  5939. for $line (@main::DefaultView)
  5940. {
  5941. printf CLIENTVIEW $line;
  5942. ### push @clientview, $line;
  5943. }
  5944. close(CLIENTVIEW);
  5945. $verb = "Creating";
  5946. }
  5947. else
  5948. {
  5949. #
  5950. # read the existing client view into @main::ExistingView
  5951. #
  5952. SDX:GetClientView("enlist", $serverport, $main::SDClient);
  5953. #
  5954. # concat the existing view and the default view
  5955. #
  5956. for $line (@main::ExistingView)
  5957. {
  5958. push @main::tmpView, $line;
  5959. }
  5960. for $line (@main::DefaultView)
  5961. {
  5962. push @main::tmpView, $line;
  5963. }
  5964. $main::V3 and do
  5965. {
  5966. print "\nexisting + default:\n";
  5967. print @main::tmpView;
  5968. };
  5969. #
  5970. # sort the list for uniqueness, preserving order
  5971. #
  5972. %seen = ();
  5973. @uniq = ();
  5974. foreach $line (@main::tmpView)
  5975. {
  5976. #
  5977. # lowercase the line for the check, but push the
  5978. # unchanged version of line onto the list so
  5979. # we preserve the user's case
  5980. #
  5981. unless ($seen{"\L$line"})
  5982. {
  5983. $seen{"\L$line"} = 1;
  5984. push @uniq, $line;
  5985. }
  5986. }
  5987. @main::FinalView = @uniq;
  5988. $main::V3 and do
  5989. {
  5990. print "\nfinal view:\n";
  5991. print @main::FinalView;
  5992. };
  5993. #
  5994. # now finish writing the client view by appending the
  5995. # final view spec
  5996. #
  5997. open(CLIENTVIEW, ">>$main::ClientView") or die("\nCan't open $main::ClientView for writing.\n");
  5998. for $viewline (@main::FinalView)
  5999. {
  6000. printf CLIENTVIEW $viewline;
  6001. }
  6002. close(CLIENTVIEW);
  6003. $verb = "Updating existing";
  6004. $repairing and $verb = "Verifying";
  6005. }
  6006. printf "\n%s client %s in depot %s.\n", $verb, $main::SDClient, $serverport;
  6007. $main::V1 and do
  6008. {
  6009. $main::V2 and do
  6010. {
  6011. printf "\ndepot mapping for %s (//%s) consists of %s project(s):\n\n", $serverport, $depotname, $#main::ProjectsInThisDepot+1;
  6012. foreach $project (@main::ProjectsInThisDepot)
  6013. {
  6014. printf "\t%s\n", @$project[$main::CBMProjectField];
  6015. }
  6016. };
  6017. print "\n\n";
  6018. system "type $main::ClientView 2>&1";
  6019. print "\n--------------------------------------------------\n\n";
  6020. };
  6021. }
  6022. # _____________________________________________________________________________
  6023. #
  6024. # WriteDefaultView
  6025. #
  6026. # Create the default view lines for this depot/project and push them onto a list
  6027. #
  6028. # Parameters:
  6029. #
  6030. # Output:
  6031. #
  6032. # _____________________________________________________________________________
  6033. sub WriteDefaultView()
  6034. {
  6035. $serverport = $_[0];
  6036. $depotname = $_[1];
  6037. $proj = "";
  6038. $group = "";
  6039. $projroot = "";
  6040. @main::DefaultView = ();
  6041. $main::V3 and do
  6042. {
  6043. print "sp = '$serverport'\n";
  6044. print "depotname = '$depotname'\n";
  6045. };
  6046. #
  6047. # for each project in this depot, generate the depot mappings and push
  6048. # them onto a list
  6049. #
  6050. foreach $project (@main::ProjectsInThisDepot)
  6051. {
  6052. $usingroot = $main::FALSE;
  6053. $proj = @$project[$main::CBMProjectField];
  6054. $group = @$project[$main::CBMGroupField];
  6055. $projroot = @$project[$main::CBMProjectRootField];
  6056. #
  6057. # flip any '\' in the proj root path into '/' for SD
  6058. #
  6059. $projroot =~ s/\\/\//g;
  6060. #
  6061. # special case for enlisting a project directly in the root
  6062. #
  6063. if ($projroot eq "sdxroot")
  6064. {
  6065. $usingroot = $main::TRUE;
  6066. }
  6067. #
  6068. # if no project root was given in the codebase map,
  6069. # assume the root is same as the project name
  6070. #
  6071. if (!$projroot)
  6072. {
  6073. $projroot = $proj;
  6074. }
  6075. #
  6076. # create and save the view line for this project
  6077. #
  6078. # handle special case for SD sources
  6079. # handle special case for enlisting directly in %SDXROOT%
  6080. # otherwise handle normal case
  6081. #
  6082. #
  6083. # see if this project is one for which we should exclude
  6084. # some platform-specific dirs from its view
  6085. #
  6086. $found = $main::FALSE;
  6087. $Exclude = $main::FALSE;
  6088. foreach $someproj (@main::PlatformProjects)
  6089. {
  6090. if ("\U$proj" eq "\U$someproj")
  6091. {
  6092. $found = $main::TRUE;
  6093. }
  6094. }
  6095. if ($found && $main::Exclusions)
  6096. {
  6097. $Exclude = $main::TRUE;
  6098. if ("\U$main::Platform" eq "X86")
  6099. {
  6100. }
  6101. if ("\U$main::Platform" eq "AMD64")
  6102. {
  6103. @ExcludePlats = ("x86", "i386", "ia64");
  6104. }
  6105. if ("\U$main::Platform" eq "IA64")
  6106. {
  6107. @ExcludePlats = ("x86", "i386", "amd64");
  6108. }
  6109. }
  6110. #
  6111. # special case for handling the one project in the codebase map that can be enlisted directly
  6112. # in $main::SDXRoot
  6113. #
  6114. if ($usingroot)
  6115. {
  6116. $projroot = $proj;
  6117. #
  6118. # maybe restrict the scope of the root mapping
  6119. #
  6120. $rootspec = "...";
  6121. $main::RestrictRoot and do
  6122. {
  6123. $rootspec = "*";
  6124. };
  6125. #
  6126. # generate some shorthand for the depot-branch-project on LHS of the view
  6127. #
  6128. my $dbp = SDX::MakeDBP($serverport, $depotname, $group, $projroot);
  6129. #
  6130. # if this is the tools project and the user wants the minimal
  6131. # tool set, customize the view
  6132. #
  6133. # else generate the normal view line
  6134. #
  6135. my $mintools = ("\U$proj" eq "\U$main::ToolsProject" and $main::MinimalTools);
  6136. if ($mintools)
  6137. {
  6138. #
  6139. # add '/' if we have a tools path
  6140. #
  6141. my $tpath = ($main::ToolsPath ? "/$main::ToolsPath" : "");
  6142. #
  6143. # flip any '\' in the tools path into '/' for SD
  6144. #
  6145. $tpath =~ s/\\/\//g;
  6146. #
  6147. # -//depot/<branch>/<toolsproj>/... //<client>/...
  6148. #
  6149. $viewline = sprintf("\t-//%s/... //%s/...\n", $dbp, $main::SDClient);
  6150. push @main::DefaultView, $viewline;
  6151. #
  6152. # //depot/<branch>/<toolsproj>/* //<client>/*
  6153. #
  6154. $viewline = sprintf("\t//%s/* //%s/*\n", $dbp, $main::SDClient);
  6155. push @main::DefaultView, $viewline;
  6156. #
  6157. # //depot/<branch>/<toolsproj>[/<toolspath>/]* //<client>[/<toolspath>/]*
  6158. #
  6159. $viewline = sprintf("\t//%s%s/* //%s%s/*\n", $dbp, $tpath, $main::SDClient, $tpath);
  6160. push @main::DefaultView, $viewline;
  6161. #
  6162. # //depot/<branch>/<toolsproj>[/<toolspath>]/<PA>/*sd*exe //<client>[/<toolspath>]/<PA>/*sd*exe
  6163. #
  6164. $viewline = sprintf("\t//%s%s/%s/*sd*exe //%s%s/%s/*sd*exe\n", $dbp, $tpath, $main::Platform, $main::SDClient, $tpath, $main::Platform);
  6165. push @main::DefaultView, $viewline;
  6166. #
  6167. # //depot/<branch>/<toolsproj>[/<toolspath>]/<PA>/perl/... //<client>[/<toolspath>]/<PA>/perl/...
  6168. #
  6169. $viewline = sprintf("\t//%s%s/%s/perl/... //%s%s/%s/perl/...\n", $dbp, $tpath, $main::Platform, $main::SDClient, $tpath, $main::Platform);
  6170. push @main::DefaultView, $viewline;
  6171. }
  6172. else
  6173. {
  6174. $viewline = sprintf("\t//%s/%s //%s/%s\n", $dbp, $rootspec, $main::SDClient, $rootspec);
  6175. push @main::DefaultView, $viewline;
  6176. }
  6177. #
  6178. # if it's NT (or a codebase that uses NT's Root depot) and exclusionary mappings are allowed,
  6179. # restrict the user's view of \developer to just themselves
  6180. #
  6181. $main::Exclusions and do
  6182. {
  6183. ### HACKHACK -- rm check on $main::RestrictRoot when old NTTEST CBM goes away
  6184. #
  6185. # BUGBUG-2000/01/18-jeffmcd -- add keyword USERSDIR=<some dir relative to root containing user-specific files>
  6186. #
  6187. (
  6188. "\U$main::CodeBase" eq "NT" or
  6189. ("\U$main::CodeBase" eq "NTTEST" and !$main::RestrictRoot) or
  6190. "\U$main::CodeBase" eq "NTSDK" or
  6191. "\U$main::CodeBase" eq "NT.INTL" or
  6192. "\U$main::CodeBase" eq "MPC" or
  6193. "\U$main::CodeBase" eq "NGWS" or
  6194. "\U$main::CodeBase" eq "MGMT" or
  6195. "\U$main::CodeBase" eq "MOM" or
  6196. "\U$main::CodeBase" eq "PDDEPOT" or
  6197. "\U$main::CodeBase" eq "WINMEDIA" or
  6198. "\U$main::CodeBase" eq "WINSS"
  6199. ) and do
  6200. {
  6201. #
  6202. # this negation line isn't necessary if we're doing minimal tools
  6203. #
  6204. !$mintools and do
  6205. {
  6206. $viewline = sprintf("\t-//%s/developer/... //%s/developer/...\n", $dbp, $main::SDClient);
  6207. push @main::DefaultView, $viewline;
  6208. };
  6209. $viewline = sprintf("\t//%s/developer/* //%s/developer/*\n", $dbp, $main::SDClient);
  6210. push @main::DefaultView, $viewline;
  6211. $viewline = sprintf("\t//%s/developer/%s/... //%s/developer/%s/...\n", $dbp, $main::SDUser, $main::SDClient, $main::SDUser);
  6212. push @main::DefaultView, $viewline;
  6213. };
  6214. };
  6215. #
  6216. # only do the exclude lines if the root isn't already restricted
  6217. # and we're not doing minimal tools (since everything in Root will
  6218. # already be restricted except what the user needs)
  6219. #
  6220. if ($Exclude && !$main::RestrictRoot && !$main::MinimalTools)
  6221. {
  6222. for $e (@ExcludePlats)
  6223. {
  6224. #
  6225. # generate the view line and save it away
  6226. #
  6227. $viewline = sprintf("\t-//%s/.../%s/... //%s/.../%s/...\n", $dbp, $e, $main::SDClient, $e);
  6228. push @main::DefaultView, $viewline;
  6229. }
  6230. }
  6231. }
  6232. else
  6233. {
  6234. #
  6235. # generate the view line(s)
  6236. #
  6237. #
  6238. # for the USERS project in Scratch depots, only map in \users\<this user>
  6239. #
  6240. # BUGBUG-2000/01/10-jeffmcd -- remove this when enlisting with <project>\path\path\path is supported
  6241. #
  6242. if ("\U$main::CodeBase" eq "SCRATCH" and $projroot eq "users")
  6243. {
  6244. # shorthand
  6245. my $dbp = SDX::MakeDBP($serverport, $depotname, $group, $projroot);
  6246. # -//depot/<branch>/users/... //<client>/users/...
  6247. $viewline = sprintf("\t-//%s/... //%s/%s/...\n", $dbp, $main::SDClient, $projroot);
  6248. push @main::DefaultView, $viewline;
  6249. # //depot/<branch>/users/<this user>/... //<client>/users/<this user>/...
  6250. $viewline = sprintf("\t//%s/%s/... //%s/%s/%s/...\n", $dbp, $main::SDUser, $main::SDClient, $projroot, $main::SDUser);
  6251. push @main::DefaultView, $viewline;
  6252. }
  6253. else
  6254. {
  6255. #
  6256. # the form of the project root depends on project type and codebase
  6257. #
  6258. my $proot = SDX::MakeProjectRoot($proj, $projroot);
  6259. #
  6260. # some shorthand
  6261. #
  6262. my $dbp = SDX::MakeDBP($serverport, $depotname, $group, $proj);
  6263. my $mintools = ("\U$main::ToolsProject" eq "\U$proj" and $main::MinimalTools);
  6264. #
  6265. # if $proj is the tools project and the user wants the minimal
  6266. # tool set, customize the view
  6267. #
  6268. # else generate the normal view line
  6269. #
  6270. if ($mintools)
  6271. {
  6272. #
  6273. # add '/' if we have a tools path
  6274. # add "/<project root>" if type 2 depot
  6275. #
  6276. my $tpath = ($main::ToolsPath ? "/$main::ToolsPath" : "");
  6277. #
  6278. # flip any '\' in the tools path into '/' for SD
  6279. #
  6280. $tpath =~ s/\\/\//g;
  6281. #
  6282. # 1: -//depot/<branch>/<proj>/... //<client>/...
  6283. # 2: -//depot/<branch>/<proj>/... //<client>/<project root>/...
  6284. #
  6285. $viewline = sprintf("\t-//%s/... //%s%s/...\n", $dbp, $main::SDClient, $proot);
  6286. push @main::DefaultView, $viewline;
  6287. #
  6288. # 1: //depot/<branch>/<proj>/<toolspath>/* //<client>/<toolspath>/*
  6289. # 2: //depot/<branch>/<proj>/<toolspath>/* //<client>/<project root>/<toolspath>/*
  6290. #
  6291. $viewline = sprintf("\t//%s%s/* //%s%s%s/*\n", $dbp, $tpath, $main::SDClient, $proot, $tpath);
  6292. push @main::DefaultView, $viewline;
  6293. #
  6294. # 1: //depot/<branch>/<proj>/<toolspath>/<PA>/*sd*exe //<client>/<toolspath>/<PA>/*sd*exe
  6295. # 2: //depot/<branch>/<proj>/<toolspath>/<PA>/*sd*exe //<client>/<project root>/<toolspath>/<PA>/*sd*exe
  6296. #
  6297. $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);
  6298. push @main::DefaultView, $viewline;
  6299. #
  6300. # 1: //depot/<branch>/<proj>/<toolspath>/<PA>/perl/... //<client>/<toolspath>/<PA>/perl/...
  6301. # 2: //depot/<branch>/<proj>/<toolspath>/<PA>/perl/... //<client>/<project root>/<toolspath>/<PA>/perl/...
  6302. #
  6303. $viewline = sprintf("\t//%s%s/%s/perl/... //%s%s%s/%s/perl/...\n", $dbp, $tpath, $main::Platform, $main::SDClient, $proot, $tpath, $main::Platform);
  6304. push @main::DefaultView, $viewline;
  6305. }
  6306. else
  6307. {
  6308. #
  6309. # 1: //depot/<branch>/project/... //<client>/...
  6310. # 2: //depot/<branch>/<project>/... //<client>/<project root>/...
  6311. #
  6312. $viewline = sprintf("\t//%s/... //%s%s/...\n", $dbp, $main::SDClient, $proot);
  6313. push @main::DefaultView, $viewline;
  6314. }
  6315. }
  6316. #
  6317. # add exclude lines to the view if this project is marked as
  6318. # having multiple platforms in the codebase map
  6319. #
  6320. if ($Exclude)
  6321. {
  6322. # shorthand
  6323. my $dbp = "$depotname/$main::Branch/$proj";
  6324. for $e (@ExcludePlats)
  6325. {
  6326. #
  6327. # generate the view line and save it away
  6328. #
  6329. # for type 1 projects (1 project/depot) project name can't be in RHS
  6330. #
  6331. # for type 2 projects (N projects/depot) project name must be in RHS
  6332. #
  6333. my $proot = SDX::MakeProjectRoot($proj, $projroot);
  6334. $viewline = sprintf("\t-//%s/.../%s/... //%s%s/.../%s/...\n", $dbp, $e, $main::SDClient, $proot, $e);
  6335. push @main::DefaultView, $viewline;
  6336. }
  6337. }
  6338. }
  6339. }
  6340. $main::V2 and do
  6341. {
  6342. print "\ndefault view --------------------\n";
  6343. for $line (@main::DefaultView)
  6344. {
  6345. print "$line";
  6346. }
  6347. print "---------------------------------\n";
  6348. };
  6349. }
  6350. # _____________________________________________________________________________
  6351. #
  6352. # MakeDBP
  6353. #
  6354. # builds depot-branch-project string depending on project's group
  6355. #
  6356. # Parameters:
  6357. #
  6358. # Output:
  6359. #
  6360. # string
  6361. #
  6362. # _____________________________________________________________________________
  6363. sub MakeDBP()
  6364. {
  6365. my $sp = $_[0];
  6366. my $depotname = $_[1];
  6367. my $group = $_[2];
  6368. my $projroot = $_[3];
  6369. my $path = "//$depotname/$main::Branch/$projroot";
  6370. $main::V3 and do
  6371. {
  6372. print "\nmakedbp: sp = '$sp'\n";
  6373. print "makedbp: depotname = '$depotname'\n";
  6374. print "makedbp: group = '$group'\n";
  6375. print "makedbp: projroot = '$projroot'\n\n";
  6376. print "makedbp: path = '$path'\n\n";
  6377. };
  6378. #
  6379. # start with depot name
  6380. #
  6381. my $dbp = $depotname;
  6382. #
  6383. # determine branch
  6384. #
  6385. # NTDEV projects have lab branches, so we can use whichever one the user wants
  6386. #
  6387. # non-NTDEV projects (like Test, Spec, Intl projects) may or may not have the
  6388. # user's lab branch -- if it exists, use it, else default to the master branch
  6389. #
  6390. if (("\U$group" eq "NTDEV") or (SDX::BranchExists($main::Branch, $sp, $path, "by-path")))
  6391. {
  6392. $dbp .= "/$main::Branch/";
  6393. }
  6394. else
  6395. {
  6396. $dbp .= "/$main::MasterBranch/";
  6397. }
  6398. #
  6399. # add the project root
  6400. #
  6401. $dbp .= $projroot;
  6402. $main::V3 and print "makedbp: returning '$dbp'\n";
  6403. return $dbp;
  6404. }
  6405. # _____________________________________________________________________________
  6406. #
  6407. # ClientExists
  6408. #
  6409. # Determine if $main::SDClient exists in the given depot
  6410. #
  6411. # Parameters:
  6412. #
  6413. # Output:
  6414. #
  6415. # TRUE if client found in depot, FALSE otherwise
  6416. # _____________________________________________________________________________
  6417. sub ClientExists()
  6418. {
  6419. my $serverport = $_[0];
  6420. my $client = $_[1];
  6421. my @out = ();
  6422. my $found = $main::FALSE;
  6423. #
  6424. # list clients and grep for client name
  6425. #
  6426. @out = `sd.exe -p $serverport clients 2>&1`;
  6427. (grep /Client $client /i, @out) and $found = $main::TRUE;
  6428. #
  6429. # die if we're ever denied access
  6430. #
  6431. SDX::AccessDenied(\@out, $serverport) and die("\n");
  6432. return $found;
  6433. }
  6434. # _____________________________________________________________________________
  6435. #
  6436. # BranchExists
  6437. #
  6438. # Determine if a branch exists in the given depot
  6439. #
  6440. # Parameters:
  6441. #
  6442. # Output:
  6443. #
  6444. # TRUE if found, FALSE otherwise
  6445. # _____________________________________________________________________________
  6446. sub BranchExists()
  6447. {
  6448. my $branch = $_[0];
  6449. my $sp = "-p $_[1]";
  6450. my $path = $_[2];
  6451. my $method = $_[3];
  6452. $main::V2 and do
  6453. {
  6454. print "\nbranchexists: branch = '$branch'\n";
  6455. print "branchexists: sp = '$sp'\n";
  6456. print "branchexists: path = '$path'\n";
  6457. print "branchexists: method = '$method'\n\n";
  6458. };
  6459. #
  6460. # list branches and look for branch name
  6461. #
  6462. ($method eq "by-name") and do
  6463. {
  6464. grep(/Branch $branch/i, `sd.exe $sp branches 2>&1`) and return 1;
  6465. };
  6466. #
  6467. # see if //<depot>/<branch>/<project> is found
  6468. #
  6469. # sd dirs is unreliable, so look at the first line returned by sd files ...
  6470. #
  6471. ($method eq "by-path") and do
  6472. {
  6473. my @out = ();
  6474. open FILE, "sd.exe $sp files $path/... 2>&1 |" or die("\nBranchExists: can't open pipe.\n");
  6475. while (<FILE>) { push @out, $_; last; }
  6476. close FILE;
  6477. grep(/ no such /, @out) and return 0;
  6478. return 1;
  6479. };
  6480. return 0;
  6481. }
  6482. # _____________________________________________________________________________
  6483. #
  6484. # GetClientView
  6485. #
  6486. # Read the existing client view out of the depot for this client. Split it into
  6487. # header and view lines. If enlisting/defecting, write the header directly to the
  6488. # new client view file.
  6489. #
  6490. # Parameters:
  6491. # serverport depot server:port pair
  6492. # client SDClient name to look up
  6493. #
  6494. # Output:
  6495. # populates @main::ExistingView if repairing
  6496. # writes $main::ClientView if enlisting/defecting
  6497. # _____________________________________________________________________________
  6498. sub GetClientView()
  6499. {
  6500. my $enlisting = ($_[0] eq "enlist");
  6501. my $defecting = ($_[0] eq "defect");
  6502. my $repairing = ($_[0] eq "repair");
  6503. my @view = ();
  6504. $serverport = $_[1];
  6505. $client = $_[2];
  6506. @main::ExistingView = ();
  6507. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in GetClientView().\n");
  6508. #
  6509. # dump the client view spec
  6510. #
  6511. @view = `sd.exe -p $serverport client -o $client 2>&1`;
  6512. #
  6513. # read the viewspec and maybe write the header for the new client view
  6514. #
  6515. ($enlisting || $defecting) and (open(CLIENTVIEW, ">$main::ClientView") or die("\nCan't open $main::ClientView for writing.\n"));
  6516. $header = $main::TRUE;
  6517. foreach $line (@view)
  6518. {
  6519. #
  6520. # throw away comments and blank lines
  6521. #
  6522. $line =~ /^#/ and next;
  6523. $line =~ /^[\t\s]*$/ and next;
  6524. #
  6525. # if we're still in the header, right the line directly
  6526. # to the new view
  6527. # otherwise push the view line into a list for later use
  6528. #
  6529. if ($header)
  6530. {
  6531. ($enlisting || $defecting) and printf CLIENTVIEW $line;
  6532. }
  6533. else
  6534. {
  6535. push @main::ExistingView, $line;
  6536. }
  6537. @vline = split(/[\t\s]+/,$line);
  6538. if ("\U$vline[0]" eq "VIEW:")
  6539. {
  6540. $header = $main::FALSE;
  6541. }
  6542. }
  6543. ($enlisting || $defecting) and close(CLIENTVIEW);
  6544. $main::V3 and do
  6545. {
  6546. # print "\nexisting view header:\n";
  6547. # system "type $main::ClientView";
  6548. print "\nexisting view -------------------\n";
  6549. print "'@main::ExistingView'\n";
  6550. print "---------------------------------\n";
  6551. };
  6552. }
  6553. # _____________________________________________________________________________
  6554. #
  6555. # UpdateSDMap
  6556. #
  6557. # Creates or updates %SDXROOT%\SD.MAP, containing a list of projects and relative
  6558. # paths to their roots in the enlistment where the SD.INI can be found.
  6559. #
  6560. # Leaves these files read-only so they stay nailed down when we delete /S.
  6561. #
  6562. # Parameters:
  6563. #
  6564. # Output:
  6565. # _____________________________________________________________________________
  6566. sub UpdateSDMap
  6567. {
  6568. my $op = $_[0];
  6569. my $enlisting = ($op eq "enlist");
  6570. my $defecting = ($op eq "defect");
  6571. my $repairing = ($op eq "repair");
  6572. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in UpdateSDMap().\n");
  6573. @main::tmpMap = ();
  6574. #
  6575. # if we're doing a clean enlist (ie no SD.MAP exists), use the default map
  6576. # else merge the default map with the existing map
  6577. #
  6578. ($enlisting || $repairing) and do
  6579. {
  6580. if (!(-e $main::SDMap))
  6581. {
  6582. printf "%s SD.MAP", $enlisting ? "Creating" : "Restoring";
  6583. @null = ();
  6584. SDX::WriteSDMap(\@null);
  6585. print "\n";
  6586. }
  6587. else
  6588. {
  6589. printf "%s SD.MAP", $enlisting ? "Updating" : "Repairing";
  6590. #
  6591. # load the default map into @main::DefaultMap
  6592. # and write the SD.INIs
  6593. #
  6594. SDX:WriteDefaultMap($main::Null, $main::Null);
  6595. #
  6596. # load the existing map into @main::ExistingMap
  6597. #
  6598. SDX::GetMapProjects($op);
  6599. #
  6600. # concat these two lists
  6601. #
  6602. for $line (@main::DefaultMap)
  6603. {
  6604. push @main::tmpMap, $line;
  6605. }
  6606. for $line (@main::ExistingMap)
  6607. {
  6608. push @main::tmpMap, $line;
  6609. }
  6610. $main::V1 and do
  6611. {
  6612. print "\ntmp map:\n\t";
  6613. print @main::tmpMap;
  6614. };
  6615. #
  6616. # unique-ify and sort them
  6617. #
  6618. %seen = ();
  6619. foreach $line (@main::tmpMap)
  6620. {
  6621. $seen{$line}++;
  6622. }
  6623. @uniq = keys %seen;
  6624. $main::V1 and do
  6625. {
  6626. print "\nuniq map:\n\t";
  6627. print @uniq;
  6628. };
  6629. @sorted = sort @uniq;
  6630. $main::V3 and do
  6631. {
  6632. print "\nsorted:\n\t";
  6633. print @sorted;
  6634. };
  6635. #
  6636. # write it
  6637. #
  6638. SDX::WriteSDMap(\@sorted);
  6639. print "\n";
  6640. }
  6641. };
  6642. $defecting and do
  6643. {
  6644. if ($main::DefectAll)
  6645. {
  6646. SDX::KillSDMap();
  6647. }
  6648. else
  6649. {
  6650. print "Removing projects from SD.MAP";
  6651. #
  6652. # load the default map into @main::DefaultMap
  6653. #
  6654. SDX:WriteDefaultMap($main::Null,$main::Null);
  6655. #
  6656. # load the existing map into @main::ExistingMap
  6657. #
  6658. if (SDX::GetMapProjects($op))
  6659. {
  6660. #
  6661. # use the existing map lines as keys to a hash,
  6662. # lowercasing them to ignore upper/lowercase
  6663. # distinctions
  6664. #
  6665. # for each line in the default map, mark it as
  6666. # removed from the hash of existing lines
  6667. #
  6668. # write the unmarked hash lines back into the list
  6669. # and sort it
  6670. #
  6671. @tmpmap = ();
  6672. %existingmap = ();
  6673. foreach $em (@main::ExistingMap)
  6674. {
  6675. $existingmap{"\L$em"} = 1;
  6676. }
  6677. $main::V3 and do
  6678. {
  6679. print "\n\nexistingmap:\n";
  6680. while (($k,$v) = each %existingmap)
  6681. {
  6682. printf "%40s %s\n", $k, $v;
  6683. }
  6684. };
  6685. foreach $dm (@main::DefaultMap)
  6686. {
  6687. if ($existingmap{"\L$dm"} == 1)
  6688. {
  6689. $existingmap{"\L$dm"} = 0;
  6690. }
  6691. }
  6692. $main::V2 and print "\nexistingmap, edited:\n";
  6693. while (($k,$v) = each %existingmap)
  6694. {
  6695. $v and push @tmpmap, $k;
  6696. $main::V2 and do
  6697. {
  6698. my $vv = (!$v) ? " $v" : $v;
  6699. printf "%40s %s\n", $k, $vv;
  6700. }
  6701. }
  6702. @sorted = sort @tmpmap;
  6703. $main::V3 and do
  6704. {
  6705. print "\nsorted:\n\t";
  6706. print @sorted;
  6707. };
  6708. #
  6709. # at this point, if we still have something to write in the map file,
  6710. # write it out
  6711. # else remove whatever's left of it
  6712. #
  6713. # this will happen in the case where there are no DefaultProjects in
  6714. # the codebase map and the user lists all known projects on the defect
  6715. # cmd line
  6716. #
  6717. ($main::V3 and @sorted) and print "\n\t\@sorted not empty.\n";
  6718. ($main::V3 and !@sorted) and print "\n\t\@sorted empty.\n";
  6719. if (@sorted)
  6720. {
  6721. SDX::WriteSDMap(\@sorted);
  6722. print "\n";
  6723. }
  6724. else
  6725. {
  6726. SDX::KillSDMap();
  6727. }
  6728. }
  6729. }
  6730. };
  6731. #
  6732. # if we still have a map file, make it RO, hidden
  6733. #
  6734. (-e $main::SDMap) and system "attrib +R +H $main::SDMap >nul 2>&1";
  6735. }
  6736. # _____________________________________________________________________________
  6737. #
  6738. # WriteSDMap
  6739. #
  6740. # Parameters:
  6741. #
  6742. # Output:
  6743. # _____________________________________________________________________________
  6744. sub WriteSDMap
  6745. {
  6746. my ($sorted) = $_;
  6747. $main::V3 and print "\n\nwritesdmap: sorted = @sorted\n";
  6748. system "attrib -R -H -S $main::SDMap >nul 2>&1";
  6749. open(SDMAP, ">$main::SDMap") or die("\nCan't open $main::SDMap for writing.\n");
  6750. print SDMAP "#\n# SD.MAP -- autogenerated by SDX -- do not edit\n#\n";
  6751. print SDMAP "\nCODEBASE = $main::CodeBase\n";
  6752. SDX::WriteSDMapCodeBaseType($main::CodeBaseType, *SDMAP);
  6753. print SDMAP "BRANCH = $main::Branch\n";
  6754. print SDMAP "CLIENT = $main::SDClient\n";
  6755. print SDMAP "\n#\n# project root\n# ------------------- -----------------------------------------------------\n";
  6756. #
  6757. # if we have a sorted list of projects, print them,
  6758. # else write the default list
  6759. #
  6760. if (@sorted)
  6761. {
  6762. foreach $line (@sorted)
  6763. {
  6764. @fields = split(/=/, $line);
  6765. printf SDMAP "%21s = %-52s\n", $fields[0], $fields[1];
  6766. }
  6767. }
  6768. else
  6769. {
  6770. #
  6771. # append the default map lines to SD.MAP
  6772. #
  6773. SDX::WriteDefaultMap("append",*SDMAP);
  6774. }
  6775. #
  6776. # print the list of enlisted depots
  6777. #
  6778. SDX::WriteSDMapDepots(\@main::ActiveDepots, *SDMAP);
  6779. close(SDMAP);
  6780. }
  6781. # _____________________________________________________________________________
  6782. #
  6783. # WriteSDMapDepots
  6784. #
  6785. # add list of enlisted depots to SD.MAP
  6786. #
  6787. # Parameters:
  6788. #
  6789. # Output:
  6790. # _____________________________________________________________________________
  6791. sub WriteSDMapDepots
  6792. {
  6793. my ($depots) = $_[0];
  6794. my $sdmap = $_[1];
  6795. my $list = "";
  6796. for $d (@$depots)
  6797. {
  6798. $d =~ /\:/ and do
  6799. {
  6800. $list .= "$d ";
  6801. };
  6802. }
  6803. $main::V3 and do
  6804. {
  6805. print "\nabout to write depot list = '$list'\n";
  6806. };
  6807. print $sdmap "\n#\n# depots\n#\n";
  6808. print $sdmap "DEPOTS = $list\n\n";
  6809. }
  6810. # _____________________________________________________________________________
  6811. #
  6812. # WriteSDMapCodeBaseType
  6813. #
  6814. # add codebase type to SD.MAP
  6815. #
  6816. # Parameters:
  6817. #
  6818. # Output:
  6819. # _____________________________________________________________________________
  6820. sub WriteSDMapCodeBaseType
  6821. {
  6822. my $type = $_[0];
  6823. my $sdmap = $_[1];
  6824. print $sdmap "CODEBASETYPE = $type\n";
  6825. }
  6826. # _____________________________________________________________________________
  6827. #
  6828. # KillSDMap
  6829. #
  6830. # Parameters:
  6831. #
  6832. # Output:
  6833. # _____________________________________________________________________________
  6834. sub KillSDMap
  6835. {
  6836. -e $main::SDMap and do
  6837. {
  6838. print "Removing $main::SDMap\n";
  6839. system "attrib -R -H -S $main::SDMap >nul 2>&1";
  6840. unlink $main::SDMap;
  6841. };
  6842. }
  6843. # _____________________________________________________________________________
  6844. #
  6845. # WriteDefaultMap
  6846. # writes the project-specific SD.MAP lines to the actual SD.MAP (if enlisting
  6847. # clean) or pushes them onto a list so we can sort them later.
  6848. #
  6849. # Parameters:
  6850. #
  6851. # Output:
  6852. # _____________________________________________________________________________
  6853. sub WriteDefaultMap
  6854. {
  6855. my $appending = ($_[0] eq "append");
  6856. my $sdmap = $_[1];
  6857. @main::DefaultMap = ();
  6858. #
  6859. # maybe just append to the real SD.MAP, which at this point
  6860. # only contains the header
  6861. # otherwise write to a temp file
  6862. #
  6863. foreach $project (@main::ProjectsInThisDepot)
  6864. {
  6865. print ".";
  6866. $usingroot = $main::FALSE;
  6867. $proj = @$project[$main::CBMProjectField];
  6868. $serverport = @$project[$main::CBMServerPortField];
  6869. $projectroot = @$project[$main::CBMProjectRootField];
  6870. #
  6871. # if no project root was given in the codebase map,
  6872. # assume the root is same as the project name
  6873. #
  6874. if (!$projectroot)
  6875. {
  6876. $projectroot = $proj;
  6877. }
  6878. #
  6879. # special case for enlisting a project directly in the root
  6880. #
  6881. if ("\U$projectroot" eq "SDXROOT")
  6882. {
  6883. $usingroot = $main::TRUE;
  6884. $projectroot = ".";
  6885. }
  6886. #
  6887. # convert '/' to '\'
  6888. #
  6889. $projectroot =~ s/\//\\/g;
  6890. #
  6891. # push the map line onto the list so we can sort it
  6892. #
  6893. $mapline = sprintf("%s=%s", $proj, $projectroot);
  6894. push @main::DefaultMap, $mapline;
  6895. }
  6896. $appending and do
  6897. {
  6898. my @sorted = sort @main::DefaultMap;
  6899. for $line (@sorted)
  6900. {
  6901. @fields = split(/=/, $line);
  6902. printf $sdmap "%21s = %-52s\n", $fields[0], $fields[1];
  6903. }
  6904. };
  6905. $main::V1 and do
  6906. {
  6907. print "\n\ndefault map:\n\t";
  6908. for $line (@main::DefaultMap)
  6909. {
  6910. print "$line";
  6911. }
  6912. };
  6913. }
  6914. # _____________________________________________________________________________
  6915. #
  6916. # GetMapProjects
  6917. #
  6918. # Parameters:
  6919. #
  6920. # Output:
  6921. # returns 1 if map found and list created, 0 otherwise
  6922. # _____________________________________________________________________________
  6923. sub GetMapProjects
  6924. {
  6925. my $op = $_[0];
  6926. my $line = "";
  6927. @main::ExistingMap = ();
  6928. #
  6929. # read the map again since it may be changing
  6930. #
  6931. if (SDX::ReadSDMap($op, $main::Null))
  6932. {
  6933. for $p (@main::SDMapProjects)
  6934. {
  6935. $line = @$p[0] . "=" . @$p[1];
  6936. push @main::ExistingMap, $line;
  6937. }
  6938. }
  6939. $main::V3 and do
  6940. {
  6941. print "\nexisting map:\n\t";
  6942. for $line (@main::ExistingMap)
  6943. {
  6944. print "getmapproj: line = '$line'\n";
  6945. }
  6946. };
  6947. @main::ExistingMap and return 1;
  6948. return 0;
  6949. }
  6950. # _____________________________________________________________________________
  6951. #
  6952. # UpdateSDINIs
  6953. #
  6954. # If enlisting or repairing, creates an SD.INI in the root of each project which
  6955. # points SDPORT to the server:port for that project and sets SDCLIENT.
  6956. #
  6957. # If defecting,
  6958. #
  6959. # Parameters:
  6960. #
  6961. # Output:
  6962. # _____________________________________________________________________________
  6963. sub UpdateSDINIs
  6964. {
  6965. my $enlisting = ($_[0] eq "enlist");
  6966. my $defecting = ($_[0] eq "defect");
  6967. my $repairing = ($_[0] eq "repair");
  6968. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in UpdateSDINIs().\n");
  6969. ($enlisting || $repairing) and do
  6970. {
  6971. print "Writing SD.INIs in project roots";
  6972. foreach $project (@main::ProjectsInThisDepot)
  6973. {
  6974. print ".";
  6975. $usingroot = $main::FALSE;
  6976. $proj = @$project[$main::CBMProjectField];
  6977. $serverport = @$project[$main::CBMServerPortField];
  6978. $projectroot = @$project[$main::CBMProjectRootField];
  6979. #
  6980. # if no project root was given in the codebase map,
  6981. # assume the root is same as the project name
  6982. #
  6983. if (!$projectroot)
  6984. {
  6985. $projectroot = $proj;
  6986. }
  6987. #
  6988. # special case for enlisting a project directly in the root
  6989. #
  6990. if ("\U$projectroot" eq "SDXROOT")
  6991. {
  6992. $usingroot = $main::TRUE;
  6993. $projectroot = ".";
  6994. }
  6995. #
  6996. # convert '/' to '\'
  6997. #
  6998. $projectroot =~ s/\//\\/g;
  6999. #
  7000. # write the corresponding SD.INI
  7001. #
  7002. SDX::WriteSDINI($projectroot, $serverport);
  7003. }
  7004. };
  7005. $defecting and do
  7006. {
  7007. #
  7008. # sync #none the project and remove the whole thing
  7009. #
  7010. # can't just do sync #none across whole depot, since it would
  7011. # remove TOOLS dir and/or other default projects we want the user to keep
  7012. #
  7013. printf "\nDefecting client %s from projects in depot %s.\n", $main::SDClient, $serverport;
  7014. print "Please wait, syncing to remove files.";
  7015. foreach $project (@main::ProjectsInThisDepot)
  7016. {
  7017. $proj = @$project[$main::CBMProjectField];
  7018. $serverport = @$project[$main::CBMServerPortField];
  7019. $projectroot = @$project[$main::CBMProjectRootField];
  7020. #
  7021. # if no project root was given in the codebase map,
  7022. # assume the root is same as the project name
  7023. #
  7024. if (!$projectroot)
  7025. {
  7026. $projectroot = $proj;
  7027. }
  7028. #
  7029. # special case for enlisting a project directly in the root
  7030. #
  7031. if ("\U$projectroot" eq "SDXROOT")
  7032. {
  7033. $projectroot = ".";
  7034. }
  7035. #
  7036. # convert '/' to '\'
  7037. #
  7038. $projectroot =~ s/\//\\/g;
  7039. #
  7040. # maybe ghost files and remove the project
  7041. #
  7042. # specifically ignore the Tools project, it will be handled
  7043. # in FinishDefect()
  7044. #
  7045. $fullprojectroot = $main::SDXRoot . "\\" . $projectroot;
  7046. if (-e $fullprojectroot)
  7047. {
  7048. #
  7049. # sync #none to remove files
  7050. #
  7051. SDX::SyncFiles("defect", $fullprojectroot, $proj);
  7052. #
  7053. # nuke it all
  7054. #
  7055. SDX::RemoveProject($fullprojectroot, $serverport, $proj);
  7056. }
  7057. }
  7058. print "\n";
  7059. };
  7060. !$defecting and print "\nok.\n";
  7061. }
  7062. # _____________________________________________________________________________
  7063. #
  7064. # WriteSDINI
  7065. #
  7066. # Parameters:
  7067. #
  7068. # Output:
  7069. # _____________________________________________________________________________
  7070. sub WriteSDINI
  7071. {
  7072. $projectroot = $_[0];
  7073. $serverport = $_[1];
  7074. #
  7075. # write the corresponding SD.INI and make it RO, hidden
  7076. #
  7077. $fullprojectroot = $main::SDXRoot . "\\" . $projectroot;
  7078. $sdini = $fullprojectroot . "\\sd.ini";
  7079. system "mkdir $fullprojectroot >nul 2>&1";
  7080. -e $fullprojectroot or die "\nCan't create project root dir $fullprojectroot.\n";
  7081. #
  7082. # make it fully writable
  7083. #
  7084. system "attrib -R -H -S $sdini >nul 2>&1";
  7085. #
  7086. # write it
  7087. #
  7088. open(SDINI, ">$sdini") or die("\nCan't open $sdini for writing.\n");
  7089. printf SDINI "#\n# autogenerated by SDX - do not edit\n#\n";
  7090. printf SDINI "SDPORT=$serverport\n";
  7091. printf SDINI "SDCLIENT=$main::SDClient\n";
  7092. close(SDINI);
  7093. #
  7094. # make it read-only, hidden
  7095. #
  7096. system "attrib +R +H $sdini >nul 2>&1";
  7097. }
  7098. # _____________________________________________________________________________
  7099. #
  7100. # SyncFiles
  7101. #
  7102. # Parameters:
  7103. #
  7104. # Output:
  7105. # _____________________________________________________________________________
  7106. sub SyncFiles
  7107. {
  7108. my $enlisting = ($_[0] eq "enlist");
  7109. my $defecting = ($_[0] eq "defect");
  7110. my $repairing = ($_[0] eq "repair");
  7111. my $fullprojectroot = $_[1];
  7112. my $proj = $_[2];
  7113. my $root = ($proj eq "root");
  7114. my $filespec;
  7115. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in SyncFiles().\n");
  7116. $defecting and do
  7117. {
  7118. chdir $fullprojectroot or die("\nCan't chdir to $fullprojectroot.\n");
  7119. print ".";
  7120. #
  7121. # handle the root carefully
  7122. #
  7123. if ($root)
  7124. {
  7125. #
  7126. # sync files directly in the root
  7127. #
  7128. $filespec = "*";
  7129. system "sd.exe sync $filespec#none >nul 2>&1";
  7130. #
  7131. # get the list of root subdirs
  7132. #
  7133. @main::RemovableRootDirs = SDX::GetImmediateSubDirs($proj);
  7134. #
  7135. # sync in the subdirs of the root individually, except
  7136. # for the tools dir
  7137. #
  7138. foreach $dir (@main::RemovableRootDirs)
  7139. {
  7140. $cmd = "sd.exe sync $dir\\...#none 2>&1";
  7141. SDX::ShowSyncProgress($cmd, 20);
  7142. }
  7143. }
  7144. else
  7145. {
  7146. #
  7147. # only sync if we're not in the tools project
  7148. #
  7149. if ($proj ne $main::ToolsProject)
  7150. {
  7151. $filespec = "...";
  7152. $cmd = "sd.exe sync $filespec#none 2>&1";
  7153. SDX::ShowSyncProgress($cmd, 20);
  7154. }
  7155. }
  7156. chdir $main::StartDir or die("\nCan't cd to start dir $main::StartDir.\n");
  7157. };
  7158. ($enlisting || $repairing) and do
  7159. {
  7160. my @depotlist = ();
  7161. $enlisting and @depotlist = @main::EnlistDepots;
  7162. $defecting and @depotlist = @main::DefectDepots;
  7163. $repairing and @depotlist = @main::RepairDepots;
  7164. foreach $depot (@depotlist)
  7165. {
  7166. $serverport = @$depot[0];
  7167. printf "\n\nSyncing files in depot %s.", $serverport;
  7168. $cmd = "sd.exe -p $serverport -c $main::SDClient sync";
  7169. SDX::ShowSyncProgress($cmd, 20);
  7170. }
  7171. print "\n\n";
  7172. };
  7173. }
  7174. # _____________________________________________________________________________
  7175. #
  7176. # RemoveProject
  7177. #
  7178. # Parameters:
  7179. #
  7180. # Output:
  7181. # _____________________________________________________________________________
  7182. sub RemoveProject
  7183. {
  7184. my $fullprojectroot = $_[0];
  7185. my $serverport = $_[1];
  7186. my $proj = $_[2];
  7187. my $root = ($proj eq "root");
  7188. my $sdini = $fullprojectroot . "\\sd.ini";
  7189. print ".";
  7190. chdir $fullprojectroot or die("\nCan't cd to $fullprojectroot.\n");
  7191. #
  7192. # maybe remove everything in the project
  7193. #
  7194. $main::DefectWithPrejudice and do
  7195. {
  7196. #
  7197. # if we're in the root project, don't just blindly delnode
  7198. # figure out which dirs exist under the root and delete each of these,
  7199. # excluding the Tools dir
  7200. #
  7201. if ($root)
  7202. {
  7203. #
  7204. # delete only the subdirs of the root project, except
  7205. # for the tools dir
  7206. #
  7207. foreach $dir (@main::RemovableRootDirs)
  7208. {
  7209. my $path = $main::SDXRoot . "\\" . $dir;
  7210. (-e $path) and do
  7211. {
  7212. chdir $path or die("\nCan't cd to root subdir $path.\n");
  7213. system "del /F /S /Q /A:RHS *.* >nul 2>&1";
  7214. chdir $main::StartDir or die("\nCan't cd to start dir $main::StartDir.\n");
  7215. print ".";
  7216. system "rd /S /Q $path >nul 2>&1";
  7217. }
  7218. }
  7219. }
  7220. else
  7221. {
  7222. #
  7223. # only remove the project if it isn't the tools
  7224. #
  7225. if ($proj ne $main::ToolsProject)
  7226. {
  7227. system "del /F /S /Q /A:RHS *.* >nul 2>&1";
  7228. chdir $main::StartDir or die("\nCan't cd to start dir $main::StartDir.\n");
  7229. print ".";
  7230. system "rd /S /Q $fullprojectroot >nul 2>&1";
  7231. }
  7232. }
  7233. };
  7234. #
  7235. # lastly, remove SD.INI
  7236. #
  7237. system "attrib -R -H -S $sdini >nul 2>&1";
  7238. unlink $sdini;
  7239. }
  7240. # _____________________________________________________________________________
  7241. #
  7242. # GetImmediateSubDirs
  7243. #
  7244. # Ask SD for the list of dirs directly below $proj
  7245. #
  7246. # Parameters:
  7247. #
  7248. # Output:
  7249. # returns a list of subdirs
  7250. # _____________________________________________________________________________
  7251. sub GetImmediateSubDirs
  7252. {
  7253. my $proj = $_[0];
  7254. my @list = ();
  7255. my @lines = ();
  7256. my $proj2 = "";
  7257. @lines = `sd.exe dirs //depot/$main::Branch/$proj/* 2>&1`;
  7258. foreach $line (@lines)
  7259. {
  7260. if ($line =~ /no such file/)
  7261. {
  7262. @list = ();
  7263. last;
  7264. }
  7265. @fields = split(/\//,$line);
  7266. $proj2 = "\L@fields[$#fields]";
  7267. chop $proj2;
  7268. if ($main::ToolsInRoot)
  7269. {
  7270. ($proj2 ne $main::ToolsPath) and push @list, $proj2;
  7271. }
  7272. else
  7273. {
  7274. ($proj2 ne $main::ToolsProject) and push @list, $proj2;
  7275. }
  7276. }
  7277. $main::V2 and do
  7278. {
  7279. print "\n\n\ngetimmediatesubdirs: list = '@list'\n\n\n";
  7280. };
  7281. return @list;
  7282. }
  7283. # _____________________________________________________________________________
  7284. #
  7285. # ToolsEtc
  7286. #
  7287. # Puts the SD/SDX tools, batch files and aliases into the enlistment
  7288. #
  7289. # Parameters:
  7290. #
  7291. # Output:
  7292. # _____________________________________________________________________________
  7293. sub ToolsEtc
  7294. {
  7295. my $op = $_[0];
  7296. my $enlisting = ($op eq "enlist");
  7297. my $defecting = ($op eq "defect");
  7298. my $repairing = ($op eq "repair");
  7299. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in ToolsEtc().\n");
  7300. #
  7301. # if the codebase map gave us a tools project, go there and sync for the
  7302. # user, otherwise handle the tools manually
  7303. #
  7304. if ($main::ToolsProject)
  7305. {
  7306. SDX::SyncTools($op);
  7307. }
  7308. else
  7309. {
  7310. SDX::CopyTools($op);
  7311. }
  7312. #
  7313. # write or remove the script to set the SD env vars
  7314. #
  7315. SDX::WriteSDINIT($op);
  7316. #
  7317. # write or remove project navigation aliases from $main::SDMap
  7318. #
  7319. SDX::WriteAliases($op);
  7320. #
  7321. # maybe clean up files in the root
  7322. #
  7323. $defecting and $main::DefectWithPrejudice and do
  7324. {
  7325. chdir $main::SDXRoot or die("\nCan't cd to $main::SDXRoot.\n");
  7326. system "del /Q /A:-R *.* >nul 2>&1";
  7327. chdir $main::StartDir or die("\nCan't cd to start dir $main::StartDir.\n");
  7328. };
  7329. }
  7330. # _____________________________________________________________________________
  7331. #
  7332. # SyncTools
  7333. #
  7334. # Parameters:
  7335. #
  7336. # Output:
  7337. #
  7338. # _____________________________________________________________________________
  7339. sub SyncTools
  7340. {
  7341. my $op = $_[0];
  7342. my $enlisting = ($op eq "enlist");
  7343. my $defecting = ($op eq "defect");
  7344. my $repairing = ($op eq "repair");
  7345. my $n = 0;
  7346. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in SyncTools().\n");
  7347. (($enlisting and $main::NewEnlist) || ($repairing and $main::Sync)) and do
  7348. {
  7349. print "\n\nPlease wait, syncing tools $main::ToolsProjectPath.";
  7350. !(-e $main::ToolsProjectPath) and system "mkdir $main::ToolsProjectPath >nul 2>&1";
  7351. chdir $main::ToolsProjectPath;
  7352. $cmd = "sd.exe sync -f $main::ToolsProjectPath\\... 2>&1";
  7353. SDX::ShowSyncProgress($cmd, 10);
  7354. #
  7355. # make sure the SD client and PERL runtimes are read-only, since SD will leave them writable
  7356. # during the sync and susceptible to a clean build cleansing with del /s
  7357. #
  7358. system "attrib +R $main::ToolsProjectPath\\$main::Platform\\perl* >nul 2>&1";
  7359. system "attrib +R $main::ToolsProjectPath\\$main::Platform\\sd.exe >nul 2>&1";
  7360. };
  7361. }
  7362. # _____________________________________________________________________________
  7363. #
  7364. # CopyTools
  7365. #
  7366. # Parameters:
  7367. #
  7368. # Output:
  7369. # _____________________________________________________________________________
  7370. sub CopyTools
  7371. {
  7372. my $enlisting = ($_[0] eq "enlist");
  7373. my $defecting = ($_[0] eq "defect");
  7374. my $repairing = ($_[0] eq "repair");
  7375. my $tools = "sdtools";
  7376. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in CopyTools().\n");
  7377. #
  7378. # when defecting, be selective about which files we remove since most are
  7379. # in use
  7380. #
  7381. ($enlisting || $repairing) and do
  7382. {
  7383. #
  7384. # if we know the codebase map, add it to the list of things
  7385. # to copy to the tools dir
  7386. #
  7387. $main::CodeBaseMapFile and push @{$main::SDXTools{toSDTools}}, $main::CodeBaseMapFile;
  7388. #
  7389. # create the local tools dir
  7390. #
  7391. $destroot = "$main::SDXRoot\\$tools";
  7392. system "mkdir $destroot >nul 2>&1";
  7393. -e $destroot or die("\nCan't create tools dir $destroot.\n");
  7394. print "\n\nCopying Source Depot tools to $destroot";
  7395. };
  7396. foreach $file (@{$main::SDXTools{toSDXRoot}})
  7397. {
  7398. $src = "$main::StartPath\\$file";
  7399. $dest = "$main::SDXRoot\\$file";
  7400. ($enlisting || $repairing) and print "." and SDX::CopyFile($src, $dest);
  7401. $defecting and unlink $dest;
  7402. }
  7403. ($enlisting || $repairing) and do
  7404. {
  7405. foreach $file (@{$main::SDXTools{toSDTools}})
  7406. {
  7407. print ".";
  7408. $src = "$main::StartPath\\$file";
  7409. $dest = "$main::SDXRoot\\$tools\\$file";
  7410. SDX::CopyFile($src, $dest);
  7411. }
  7412. foreach $file (@{$main::SDXTools{toSDToolsPA}})
  7413. {
  7414. print ".";
  7415. $src = "$main::StartPath\\$main::Platform\\$file";
  7416. $dest = "$main::SDXRoot\\$tools\\$file";
  7417. SDX::CopyFile($src, $dest);
  7418. }
  7419. print "\nok.\n";
  7420. };
  7421. }
  7422. # _____________________________________________________________________________
  7423. #
  7424. # CopyFile
  7425. #
  7426. # Parameters:
  7427. #
  7428. # Output:
  7429. # _____________________________________________________________________________
  7430. sub CopyFile
  7431. {
  7432. $#_ == 1 or die("\nNot enough arguments to CopyFile().\n");
  7433. $src = $_[0];
  7434. $dest = $_[1];
  7435. $main::V2 and do
  7436. {
  7437. printf "\ncopy /Y /V $src $dest\n";
  7438. };
  7439. system "copy /Y /V $src $dest >nul 2>&1";
  7440. -e $dest or die("\nCan't copy $src to enlistment root $dest.\n");
  7441. }
  7442. # _____________________________________________________________________________
  7443. #
  7444. # WriteSDINIT
  7445. #
  7446. # Write the SD environment variables to a batch file for the user to run later.
  7447. #
  7448. # Parameters:
  7449. #
  7450. # Output:
  7451. # _____________________________________________________________________________
  7452. sub WriteSDINIT
  7453. {
  7454. my $enlisting = ($_[0] eq "enlist");
  7455. my $defecting = ($_[0] eq "defect");
  7456. my $repairing = ($_[0] eq "repair");
  7457. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in WriteSDINIT().\n");
  7458. #
  7459. # SDINIT.CMD goes in the tools dir if we have one
  7460. # otherwise to SDXROOT
  7461. #
  7462. $file = "\\sdinit.cmd";
  7463. if ($main::ToolsProject)
  7464. {
  7465. $main::SDINIT = $main::ToolsProjectPath . $file;
  7466. }
  7467. else
  7468. {
  7469. $main::SDINIT = $main::SDXRoot . $file;
  7470. }
  7471. #
  7472. # make it writable
  7473. #
  7474. system "attrib -R -H -S $main::SDINIT >nul 2>&1";
  7475. #
  7476. # maybe (re)write
  7477. #
  7478. (($enlisting and !(-e $main::SDINIT)) or $repairing) and do
  7479. {
  7480. open(SDINIT, ">$main::SDINIT") or die("\nCan't open $main::SDINIT for writing.\n");
  7481. printf SDINIT "\@if \"%%_ECHO%%\" == \"\" \@echo off\n\n";
  7482. printf SDINIT "rem\nrem SDINIT.CMD -- autogenerated by SDX\nrem\n\n";
  7483. printf SDINIT "set SDXROOT=%s\n", $main::SDXRoot;
  7484. printf SDINIT "set SDCONFIG=sd.ini\n";
  7485. printf SDINIT "if \"%%SDEDITOR%%\" == \"\" set SDEDITOR=notepad.exe\n";
  7486. printf SDINIT "if \"%%SDDIFF%%\" == \"\" set SDDIFF=windiff.exe\n\n";
  7487. #
  7488. # only change the user's path if there's no tools dir
  7489. #
  7490. !$main::ToolsProject and printf SDINIT "set PATH=\%SDXROOT\%\\sdtools;\%PATH\%\n\n";
  7491. if ($main::ToolsProject)
  7492. {
  7493. my $tools;
  7494. $tools = $main::ToolsProject . "\\" . $main::ToolsPath;
  7495. $main::ToolsInRoot and $tools = $main::ToolsPath;
  7496. 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;
  7497. printf SDINIT "if exist \%SDXROOT\%\\%s\sdvars.cmd call \%SDXROOT\%\\%s\sdvars.cmd\n", $tools, $tools;
  7498. }
  7499. else
  7500. {
  7501. printf SDINIT "alias -f \%SDXROOT\%\\alias.sdx -f \%SDXROOT\%\\alias.%s\n\n", $main::CodeBase;
  7502. printf SDINIT "if exist \%SDXROOT\%\\sdvars.cmd call \%SDXROOT\%\\sdvars.cmd\n";
  7503. }
  7504. close(SDINIT);
  7505. #
  7506. # make it read-only
  7507. #
  7508. system "attrib +R $main::SDINIT >nul 2>&1";
  7509. };
  7510. #
  7511. # maybe delete it
  7512. #
  7513. $defecting and unlink $main::SDINIT;
  7514. }
  7515. # _____________________________________________________________________________
  7516. #
  7517. # WriteAliases
  7518. #
  7519. # Write ALIAS.<codebase> with project-specific aliases for CD'g around the tree
  7520. #
  7521. # Parameters:
  7522. #
  7523. # Output:
  7524. # _____________________________________________________________________________
  7525. sub WriteAliases
  7526. {
  7527. my $op = $_[0];
  7528. my $enlisting = ($op eq "enlist");
  7529. my $defecting = ($op eq "defect");
  7530. my $repairing = ($op eq "repair");
  7531. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in WriteAliases().\n");
  7532. #
  7533. # ALIAS.<codebase> goes in the tools dir if we have one
  7534. # otherwise to SDXROOT
  7535. #
  7536. $file = "\\alias.";
  7537. if ($main::ToolsProject)
  7538. {
  7539. $main::ALIASES = $main::ToolsProjectPath . $file . $main::CodeBase;
  7540. }
  7541. else
  7542. {
  7543. $main::ALIASES = $main::SDXRoot . $file . $main::CodeBase;
  7544. }
  7545. #
  7546. # make it writable
  7547. #
  7548. system "attrib -R -H -S $main::ALIASES >nul 2>&1";
  7549. #
  7550. # maybe (re)write it
  7551. #
  7552. ($enlisting || $repairing) and do
  7553. {
  7554. #
  7555. # get the list of projects and roots
  7556. # need to reread the map since it may have changed
  7557. #
  7558. if (SDX::ReadSDMap($op, $main::Null))
  7559. {
  7560. open(ALIASES, ">$main::ALIASES") or die("\nCan't open $main::ALIASES for writing.\n");
  7561. print ALIASES "\n#\n# autogenerated by SDX -- do not edit\n";
  7562. print ALIASES "#\n";
  7563. #
  7564. # for each project and root, write an alias
  7565. #
  7566. foreach $projectandroot (@main::SDMapProjects)
  7567. {
  7568. $project = @$projectandroot[0];
  7569. $project =~ tr/A-Z/a-z/;
  7570. if (!exists($main::BadAliases{$project}))
  7571. {
  7572. printf ALIASES "%-24scd /d \%SDXROOT\%\\%s\\\$1\n", @$projectandroot[0], @$projectandroot[1];
  7573. }
  7574. }
  7575. close(ALIASES);
  7576. #
  7577. # make it read-only
  7578. #
  7579. system "attrib +R $main::ALIASES >nul 2>&1";
  7580. }
  7581. };
  7582. $defecting and do
  7583. {
  7584. unlink $main::ALIASES;
  7585. };
  7586. }
  7587. # _____________________________________________________________________________
  7588. #
  7589. # FilesOpen
  7590. #
  7591. # Parameters:
  7592. # $serverport
  7593. #
  7594. # Output:
  7595. # returns TRUE if the client has files opened in any of the depots, FALSE
  7596. # otherwise
  7597. # _____________________________________________________________________________
  7598. sub FilesOpen
  7599. {
  7600. my $depot;
  7601. my @open = ();
  7602. print "\nChecking for open files.";
  7603. #
  7604. # look for open files in each depot
  7605. #
  7606. foreach $depot (@main::DefectDepots)
  7607. {
  7608. print ".";
  7609. my $serverport = @$depot[0];
  7610. push @open, `sd.exe -p $serverport -c $main::SDClient opened 2>&1`;
  7611. }
  7612. my @err = ();
  7613. (@err = grep(/failed/, @open)) and do
  7614. {
  7615. print "\n\nOne or more depots are unavailable:\n\n@err\n";
  7616. die("\n");
  7617. };
  7618. $main::V3 and print "open = '@open'\n";
  7619. (@open = grep(/\/\//, @open)) and print "\nok.\n";
  7620. #
  7621. # if this list has anything in it, open files were found
  7622. #
  7623. @open;
  7624. }
  7625. # _____________________________________________________________________________
  7626. #
  7627. # GetCodeBases
  7628. #
  7629. # Parameters:
  7630. #
  7631. # Output:
  7632. #
  7633. # _____________________________________________________________________________
  7634. sub GetCodeBases
  7635. {
  7636. $rc = system "dir /B $main::StartPath\\projects.* > $main::tmptmp 2>nul";
  7637. if ($rc / 256)
  7638. {
  7639. print "\t\t(none)\n";
  7640. }
  7641. else
  7642. {
  7643. open(CBLIST, "<$main::tmptmp") or die("\nCan't open $main::tmptmp for reading.\n");
  7644. while ($line = <CBLIST>)
  7645. {
  7646. #
  7647. # trim out noise
  7648. #
  7649. chop $line;
  7650. $line =~ tr/a-z/A-Z/;
  7651. $line =~ s/PROJECTS|CMD|INC|BAT|//g;
  7652. $line =~ s/^\.//g;
  7653. if ($line)
  7654. {
  7655. printf "\t\t %s\n", $line;
  7656. }
  7657. }
  7658. close(CBLIST);
  7659. }
  7660. }
  7661. # _____________________________________________________________________________
  7662. #
  7663. # VerifyCBMap
  7664. #
  7665. # Parameters:
  7666. #
  7667. # Output:
  7668. #
  7669. # _____________________________________________________________________________
  7670. sub VerifyCBMap
  7671. {
  7672. my $codebase = $_[0];
  7673. my $rc;
  7674. #
  7675. # make sure we have the codebase map file
  7676. #
  7677. $main::CodeBaseMapFile = "projects." . $codebase;
  7678. $main::CodeBaseMap = $main::StartPath . "\\" . $main::CodeBaseMapFile;
  7679. $main::V3 and do
  7680. {
  7681. print "\nverifycbmap: codebase = '$codebase'\n";
  7682. print "verifycbmap: codebasemapfile = '$main::CodeBaseMapFile'\n";
  7683. print "verifycbmap: codebasemap = '$main::CodeBaseMap'\n";
  7684. };
  7685. return -e $main::CodeBaseMap;
  7686. }
  7687. # _____________________________________________________________________________
  7688. #
  7689. # SyncOtherDirs
  7690. #
  7691. # Parameters:
  7692. #
  7693. # Output:
  7694. #
  7695. # _____________________________________________________________________________
  7696. sub SyncOtherDirs
  7697. {
  7698. my $enlisting = ($_[0] eq "enlist");
  7699. my $defecting = ($_[0] eq "defect");
  7700. my $repairing = ($_[0] eq "repair");
  7701. (!$enlisting && !$defecting && !$repairing) and die("\nUnknown operation in SyncOtherDirs().\n");
  7702. (($enlisting and $main::NewEnlist) || $repairing) and do
  7703. {
  7704. foreach $path (@main::OtherDirs)
  7705. {
  7706. if ($path eq ".")
  7707. {
  7708. my $fullpath = $main::SDXRoot;
  7709. my $filespec = ($fullpath =~ /\\$/ ? "" : "\\") . "*";
  7710. $fullpath .= $filespec;
  7711. print "\n\nPlease wait, syncing $fullpath.";
  7712. chdir $fullpath;
  7713. print ".";
  7714. system "sd.exe sync -f $fullpath >nul 2>&1";
  7715. print ".\n\n";
  7716. }
  7717. else
  7718. {
  7719. my $fullpath = $main::SDXRoot . "\\" . $path;
  7720. print "\n\nSyncing $fullpath.";
  7721. chdir $fullpath;
  7722. print ".";
  7723. system "sd.exe sync -f $fullpath\\... >nul 2>&1";
  7724. print ".\n\n";
  7725. }
  7726. }
  7727. };
  7728. }
  7729. # _____________________________________________________________________________
  7730. #
  7731. # ReadProfile
  7732. #
  7733. # reads codebase, branch and list of projects from text file
  7734. #
  7735. # Parameters:
  7736. #
  7737. # Output:
  7738. # sets $main::ProfileCodeBase
  7739. # sets $main::ProfileBranch
  7740. # populates $main::ProfileProjects
  7741. # _____________________________________________________________________________
  7742. sub ReadProfile
  7743. {
  7744. if (-e $main::Profile)
  7745. {
  7746. open(PROFILE, "<$main::Profile") or die("\nCan't open profile $main::Profile for reading.\n");
  7747. while ($line = <PROFILE>)
  7748. {
  7749. #
  7750. # throw away comments
  7751. #
  7752. $line =~ /^#/ and next;
  7753. chop $line;
  7754. #
  7755. # get codebase name
  7756. #
  7757. if ($line =~ /^CODEBASE/)
  7758. {
  7759. @fields = split(/[\t\s]*=[\t\s]*/, $line);
  7760. $main::ProfileCodeBase = @fields[1];
  7761. $main::ProfileCodeBase =~ s/[\t\s]*//g;
  7762. }
  7763. #
  7764. # get branch to enlist
  7765. #
  7766. if ($line =~ /^BRANCH/)
  7767. {
  7768. @fields = split(/[\t\s]*=[\t\s]*/, $line);
  7769. $main::ProfileBranch = @fields[1];
  7770. $main::ProfileBranch =~ s/[\t\s]*//g;
  7771. }
  7772. #
  7773. # get any projects
  7774. #
  7775. if ($line =~ /^PROJECTS/)
  7776. {
  7777. $line =~ s/^PROJECTS[\t\s]*=[\t\s]*//g;
  7778. @main::ProfileProjects = split(/[\t\s]+/,$line);
  7779. }
  7780. }
  7781. close(PROFILE);
  7782. $main::V2 and do
  7783. {
  7784. print "\n";
  7785. printf "readprofile: codebase = '%s'\n", $main::ProfileCodeBase;
  7786. printf "readprofile: branch = '%s'\n\n", $main::ProfileBranch;
  7787. foreach $p (@main::ProfileProjects)
  7788. {
  7789. printf "readprofile: profileprojects = '%s'\n", $p;
  7790. }
  7791. };
  7792. #
  7793. # make sure we have everything
  7794. #
  7795. $main::ProfileCodeBase and $main::ProfileBranch and @main::ProfileProjects and return 1;
  7796. print "The profile\n\n\t$main::Profile\n\nis missing the ";
  7797. !$main::ProfileCodeBase and print "codebase name.\n" and return 0;
  7798. !$main::ProfileBranch and print "branch name.\n" and return 0;
  7799. !@main::ProfileProjects and print "project list.\n";
  7800. }
  7801. else
  7802. {
  7803. print "\nCan't find profile $main::Profile.\n";
  7804. }
  7805. return 0;
  7806. }
  7807. # _____________________________________________________________________________
  7808. #
  7809. # WriteDefaultSetEnv
  7810. #
  7811. # Parameters:
  7812. #
  7813. # Output:
  7814. # _____________________________________________________________________________
  7815. sub WriteDefaultSetEnv
  7816. {
  7817. return;
  7818. }
  7819. # _____________________________________________________________________________
  7820. #
  7821. # Backup
  7822. #
  7823. # Parameters:
  7824. #
  7825. # Output:
  7826. # _____________________________________________________________________________
  7827. sub Backup
  7828. {
  7829. return;
  7830. }
  7831. # _____________________________________________________________________________
  7832. #
  7833. # Restore
  7834. #
  7835. # Parameters:
  7836. #
  7837. # Output:
  7838. # _____________________________________________________________________________
  7839. sub Restore
  7840. {
  7841. return;
  7842. }
  7843. # _____________________________________________________________________________
  7844. #
  7845. # Type1Root
  7846. #
  7847. # Root: field for client view depends on codebase type
  7848. #
  7849. # for type 1 (1 project/depot), root includes project name
  7850. # for type 2 (N projects/depot), root is just main::SDXRoot
  7851. #
  7852. # Parameters:
  7853. #
  7854. # Output:
  7855. # $root
  7856. # _____________________________________________________________________________
  7857. sub Type1Root
  7858. {
  7859. my $root = $_[0];
  7860. my $project;
  7861. my $proj;
  7862. my $projroot;
  7863. #
  7864. # only one project per depot
  7865. #
  7866. $project = @main::ProjectsInThisDepot[0];
  7867. $proj = @$project[$main::CBMProjectField];
  7868. $projroot = @$project[$main::CBMProjectRootField];
  7869. #
  7870. # if no project root was given in the codebase map, assume
  7871. # the root is same as the project name
  7872. #
  7873. !$projroot and $projroot = $proj;
  7874. #
  7875. # if we're not the root project, append project name
  7876. #
  7877. !($projroot eq "sdxroot") and $root .= "\\$projroot";
  7878. return $root;
  7879. }
  7880. # _____________________________________________________________________________
  7881. #
  7882. # MakeUniqueClient
  7883. #
  7884. # Returns a client name unique in the depots if $main::SDClient already
  7885. # exists. Waits on a global mutex to guarantee name is unique.
  7886. #
  7887. # Parameters:
  7888. #
  7889. # Output:
  7890. # existing $main::SDClient if it's unique
  7891. # else a unique variation of $main::SDClient
  7892. # _____________________________________________________________________________
  7893. sub MakeUniqueClient
  7894. {
  7895. my $client = $main::SDClient;
  7896. my @list = ();
  7897. print "\nPlease wait, verifying client name $main::SDClient is available";
  7898. #
  7899. # we want to know we're the only enlist process trying to generate
  7900. # a unique client name
  7901. #
  7902. $main::V3 and print "\ncreating mutex\n";
  7903. $main::Mutex = Win32::Mutex->new($main::FALSE, "SDX_ENLIST");
  7904. #
  7905. # wait til we get it
  7906. #
  7907. $main::V3 and print "waiting on mutex\n";
  7908. $main::Mutex->wait(0x7fffffff);
  7909. $main::V3 and print "got it\n";
  7910. $main::HaveMutex = $main::TRUE;
  7911. #
  7912. # build a list of clients in each depot
  7913. #
  7914. # check for access denied as we go
  7915. #
  7916. foreach $depot (@main::VerifyDepots)
  7917. {
  7918. print ".";
  7919. $serverport = @$depot[0];
  7920. $main::V3 and print "$serverport\n";
  7921. push (@list, `sd.exe -p $serverport clients 2>&1`);
  7922. SDX::AccessDenied(\@list, $serverport) and die("\n");
  7923. }
  7924. $main::V4 and print "\n\nclient list = @list\n";
  7925. #
  7926. # loop til we have a unique name
  7927. #
  7928. $num = 1;
  7929. while (grep(/Client $client /i, @list))
  7930. {
  7931. print ".";
  7932. $client = "$main::SDClient-" . $num++;
  7933. }
  7934. #
  7935. # hang onto the mutex until we've registered the first client
  7936. # using the new name -- release it in Enlist()
  7937. #
  7938. $main::V3 and print "leaving MakeUniqueClient\n";
  7939. return $client;
  7940. }
  7941. # _____________________________________________________________________________
  7942. #
  7943. # VerifyCodeBaseAndBranch
  7944. #
  7945. #
  7946. # Parameters:
  7947. #
  7948. # Output:
  7949. # returns TRUE if error and usage needed, else FALSE
  7950. # _____________________________________________________________________________
  7951. sub VerifyCodeBaseAndBranch
  7952. {
  7953. my $codebase = $_[0];
  7954. my $branch = $_[1];
  7955. my $usage = $main::FALSE;
  7956. $main::V2 and print "codebase = '$codebase'\nbranch = '$branch'\n";
  7957. #
  7958. # verify
  7959. #
  7960. ($codebase eq "") and print "\nMissing codebase.\n" and $usage = $main::TRUE;
  7961. (substr($codebase,0,1) =~ /[\/-]/) and do
  7962. {
  7963. $codebase !~ /\?/ and print "\nCodebase name '$codebase' appears to be a command switch.\n";
  7964. $usage = $main::TRUE;
  7965. };
  7966. substr($codebase,0,1) =~ /@/ and print "\nCodebase name '$codebase' appears to be a client name.\n" and $usage = $main::TRUE;
  7967. ($branch eq "") and print "\nMissing branch.\n" and $usage = $main::TRUE;
  7968. (substr($branch,0,1) =~ /[\/-]/) and print "\nBranch name '$branch' appears to be a command switch.\n" and $usage = $main::TRUE;
  7969. return $usage;
  7970. }
  7971. # _____________________________________________________________________________
  7972. #
  7973. # AccessDenied
  7974. #
  7975. # Parameters:
  7976. # $list -- to grep for access error
  7977. # $serverport -- depot where access failed
  7978. #
  7979. # Output:
  7980. # error msg and return 1 if denied, else 0
  7981. # _____________________________________________________________________________
  7982. sub AccessDenied
  7983. {
  7984. my ($list) = $_[0];
  7985. my $serverport = $_[1];
  7986. $main::V3 and do
  7987. {
  7988. print "accessdenied: list = '@$list'\n";
  7989. print "accessdenied: serverport = '$serverport'\n";
  7990. };
  7991. grep(/ don't have permission /, @$list) and do
  7992. {
  7993. print "\n\n\nAccess denied to depot $serverport.\n";
  7994. print "\nYour domain user account must have permission to use this depot, or belong\n";
  7995. print "to a domain group that has access. Please email INFRA for assistance.\n";
  7996. return 1;
  7997. };
  7998. return 0;
  7999. }
  8000. # _____________________________________________________________________________
  8001. #
  8002. # ShowSyncProgress
  8003. #
  8004. # Parameters:
  8005. # $cmd -- sd sync cmd to run
  8006. #
  8007. # Output:
  8008. # ...
  8009. # _____________________________________________________________________________
  8010. sub ShowSyncProgress
  8011. {
  8012. my $cmd = $_[0];
  8013. my $mod = $_[1];
  8014. open FILE, "$cmd |" or die("\nShowSyncProgress: can't open pipe for $cmd.\n");
  8015. while (<FILE>) { !(++$n % $mod) and print "."; }
  8016. close FILE;
  8017. }
  8018. # _____________________________________________________________________________
  8019. #
  8020. # ShowSDProgress
  8021. #
  8022. # Parameters:
  8023. # $cmd -- sd cmd to run
  8024. #
  8025. # Output:
  8026. # ...
  8027. # _____________________________________________________________________________
  8028. sub ShowSDProgress
  8029. {
  8030. my $cmd = $_[0];
  8031. my $mod = $_[1];
  8032. open FILE, "$cmd |" or die("\nShowSDProgress: can't open pipe for $cmd.\n");
  8033. while (<FILE>) { !(++$n % $mod) and print "."; }
  8034. close FILE;
  8035. }
  8036. # _____________________________________________________________________________
  8037. #
  8038. # ServerPort
  8039. #
  8040. # for type 1 depots we're in a project root and will have an SD.INI
  8041. # to tell us server:port
  8042. # for type 2 depots rely on passed in $sp
  8043. #
  8044. # Parameters:
  8045. #
  8046. # cmd or codebase type
  8047. #
  8048. # Output:
  8049. # ...
  8050. # _____________________________________________________________________________
  8051. sub ServerPort
  8052. {
  8053. my $type = $_[0];
  8054. my $sp = $_[1];
  8055. return ($type == 2 ? "-p $sp" : "");
  8056. }
  8057. # _____________________________________________________________________________
  8058. #
  8059. # GetPublicChangeNum
  8060. #
  8061. # get the public change number from $main::SDXROOT\public\public_changenum.sd
  8062. # if there is one
  8063. #
  8064. # Parameters:
  8065. #
  8066. # Output:
  8067. # set $main::PublicChangeNum
  8068. # _____________________________________________________________________________
  8069. sub GetPublicChangeNum
  8070. {
  8071. ("\U$main::CodeBase" eq "NT") and do
  8072. {
  8073. my $pcn = "$main::SDXRoot\\public\\public_changenum.sd";
  8074. my $line = "";
  8075. if (open(FILE, "<$pcn"))
  8076. {
  8077. $line = <FILE>;
  8078. close(FILE);
  8079. #
  8080. # $line is of the form "Change XXXX created."
  8081. #
  8082. return (split(/ /, $line))[1];
  8083. }
  8084. };
  8085. return 0;
  8086. }
  8087. # _____________________________________________________________________________
  8088. #
  8089. # GetDepotTypes
  8090. #
  8091. # called by OtherOp only when executing type 2 commands
  8092. #
  8093. # Parameters:
  8094. #
  8095. # Output:
  8096. # populate %main::DepotType
  8097. # _____________________________________________________________________________
  8098. sub GetDepotTypes
  8099. {
  8100. #
  8101. # for type 2 commands read the codebase map
  8102. # and figure out the depot type
  8103. #
  8104. if (SDX::VerifyCBMap($main::CodeBase))
  8105. {
  8106. SDX::ReadCodeBaseMap();
  8107. SDX::MakePGDLists();
  8108. }
  8109. else
  8110. {
  8111. print "\n\nError: Can't find codebase map $main::CodeBaseMap.\n";
  8112. die("\nContact the SDX alias.\n");
  8113. }
  8114. }
  8115. # _____________________________________________________________________________
  8116. #
  8117. # MakeProjectRoot
  8118. #
  8119. # for type 1 projects (1 project/depot), the project name is
  8120. # included in the Root: field of the client view and must not
  8121. # be used in the RHS of the view line
  8122. #
  8123. # for type 2 projects (N projects/depot) the project can't be part
  8124. # of the root and so must be included in the RHS
  8125. #
  8126. # Parameters:
  8127. #
  8128. # Output:
  8129. # returns
  8130. # _____________________________________________________________________________
  8131. sub MakeProjectRoot
  8132. {
  8133. my $proj = $_[0];
  8134. my $projroot = $_[1];
  8135. $main::V3 and do
  8136. {
  8137. print "makeprojectroot: proj = '$proj'\n";
  8138. print "makeprojectroot: projroot = '$projroot'\n";
  8139. print "makeprojectroot: projtype{$proj} = $main::ProjectType{$proj}\n";
  8140. };
  8141. my $pr = ($main::ProjectType{$proj} == 2 ) ? "/$projroot" : "";
  8142. $main::V3 and print "makeprojectroot: returning '$pr'\n";
  8143. return $pr;
  8144. }
  8145. # _____________________________________________________________________________
  8146. #
  8147. # DepotErrors
  8148. #
  8149. # format and print the number of errors we got trying to talk to depot
  8150. #
  8151. # Parameters:
  8152. #
  8153. # Output:
  8154. # _____________________________________________________________________________
  8155. sub DepotErrors
  8156. {
  8157. my ($counters) = $_[0];
  8158. my $pad = $_[1];
  8159. my $errors = $_[2];
  8160. push @$counters, sprintf "\nSD CLIENT ERRORS:%s%s\n", $pad, $errors;
  8161. };
  8162. # _____________________________________________________________________________
  8163. #
  8164. # Changes
  8165. #
  8166. # generate build changelist summary for Main and lab branch(es)
  8167. # process all other sdx changes commands normally
  8168. #
  8169. # Parameters:
  8170. #
  8171. # Output:
  8172. # _____________________________________________________________________________
  8173. sub Changes
  8174. {
  8175. $main::V3 and do
  8176. {
  8177. print "buildnum = $main::BuildNumber\n";
  8178. print "minusb = $main::MinusB\n";
  8179. print "sdcmd = $main::SDCmd\n";
  8180. print "userargs = $main::UserArgs\n";
  8181. };
  8182. #
  8183. # if not looking for build change summary, handle sdx changes command
  8184. # normally
  8185. #
  8186. if (!$main::MinusB)
  8187. {
  8188. SDX::OtherOp($main::SDCmd, $main::UserArgs);
  8189. }
  8190. else
  8191. {
  8192. #
  8193. # return if not NT
  8194. #
  8195. ($main::CodeBase ne "NT") and do
  8196. {
  8197. print "\nsdx changes -b only supported for NT codebase.\n";
  8198. return;
  8199. };
  8200. #
  8201. # create hash of history
  8202. #
  8203. (!SDX::GetBuildHistory($main::BuildNumber)) and return;
  8204. (!$main::BuildHistory{$main::BuildNumber}{buildtype}) and do
  8205. {
  8206. print "\nCould not determine $main::BuildNumber build type from RI/integration change comments.\n";
  8207. return;
  8208. };
  8209. #
  8210. # generate the lists of changes in this build
  8211. #
  8212. $type = $main::BuildHistory{$main::BuildNumber}{buildtype};
  8213. #
  8214. # Main
  8215. #
  8216. # consists of changes from lab branch(es) and Main
  8217. #
  8218. # sdx changes -b 2271 produces
  8219. # changes.2271.main.txt
  8220. # changes.2271.lab02_n.txt
  8221. # changes.2271.lab03_n.txt
  8222. # changes.2271.lab07_n.txt
  8223. #
  8224. ($type eq "MAIN") and do
  8225. {
  8226. $main::V2 and do
  8227. {
  8228. print "\n$main::BuildNumber is an RI:\n";
  8229. SDX::PrintBH(\%main::BuildHistory, $main::BuildNumber);
  8230. };
  8231. SDX::GetMainChanges($main::BuildNumber, $type);
  8232. };
  8233. #
  8234. # BETA
  8235. #
  8236. # consists of changes from the beta branch
  8237. #
  8238. # sdx changes -b 2277 produces
  8239. # changes.2277.beta1.txt
  8240. #
  8241. ($type eq "BETA") and do
  8242. {
  8243. $main::V2 and do
  8244. {
  8245. print "\n$main::BuildNumber is a BETA:\n";
  8246. SDX::PrintBH(\%main::BuildHistory, $main::BuildNumber);
  8247. };
  8248. #
  8249. # for beta builds there's only one contributing branch, betaX
  8250. # use the first one in the list
  8251. #
  8252. my $branch = @{$main::BuildHistory{$main::BuildNumber}{branches}}[0];
  8253. SDX::GetBranchChanges($main::BuildNumber, $branch, $type);
  8254. };
  8255. #
  8256. # IDX
  8257. #
  8258. # consists of changes from the original RI build and the IDX branch
  8259. #
  8260. # sdx changes -b 2267 produces
  8261. # changes.2267.main.txt
  8262. # changes.2267.lab02_n.txt
  8263. # changes.2267.idx01.txt
  8264. #
  8265. ($type eq "IDX") and do
  8266. {
  8267. $main::V2 and do
  8268. {
  8269. print "\n$main::BuildNumber is an IDX:\n";
  8270. SDX::PrintBH(\%main::BuildHistory, $main::BuildNumber);
  8271. };
  8272. #
  8273. # get changes from the original RI build
  8274. #
  8275. SDX::GetMainChanges($main::BuildNumber, "MAIN");
  8276. #
  8277. # get changes from the IDX build
  8278. #
  8279. # for idx builds there's only one contributing branch, idx0N
  8280. # use the first one in the list
  8281. #
  8282. my $branch = (grep {/idx/} @{$main::BuildHistory{$main::BuildNumber}{branches}})[0];
  8283. SDX::GetBranchChanges($main::BuildNumber, $branch, $type);
  8284. };
  8285. }
  8286. }
  8287. # _____________________________________________________________________________
  8288. #
  8289. # GetMainChanges
  8290. #
  8291. # Parameters:
  8292. #
  8293. # Output:
  8294. # _____________________________________________________________________________
  8295. sub GetMainChanges
  8296. {
  8297. my $buildnum = $_[0];
  8298. my $type = $_[1];
  8299. my $labbranch = "";
  8300. #
  8301. # get changes that went into //depot/main for this build
  8302. #
  8303. SDX::GetBranchChanges($buildnum, "main", $type);
  8304. #
  8305. # for each lab that RI'd, get changes that went into //depot/<lab>
  8306. #
  8307. my %seen = ();
  8308. my @labbranches = sort grep {/lab/} @{$main::BuildHistory{$buildnum}{branches}};
  8309. foreach $labbranch (@labbranches)
  8310. {
  8311. $seen{$labbranch} and next;
  8312. $seen{$labbranch} = 1;
  8313. SDX::GetBranchChanges($buildnum, $labbranch, $type);
  8314. }
  8315. }
  8316. # _____________________________________________________________________________
  8317. #
  8318. # GetBranchChanges
  8319. #
  8320. # Parameters:
  8321. #
  8322. # Output:
  8323. # _____________________________________________________________________________
  8324. sub GetBranchChanges
  8325. {
  8326. my $buildnum = $_[0];
  8327. my $branch = $_[1];
  8328. my $type = $_[2];
  8329. my $project = "";
  8330. $main::Logging = $main::TRUE;
  8331. $main::Log = "$main::SDXRoot\\changes.$buildnum.$branch.txt";
  8332. unlink $main::Log;
  8333. print "\n\n\nGetting changes for $buildnum $branch...\n";
  8334. #
  8335. # get changes that went into //depot/$branch for $buildnum
  8336. #
  8337. # for each project
  8338. # get ts1, ts2
  8339. # get change list
  8340. #
  8341. foreach $proj (@main::SDMapProjects)
  8342. {
  8343. my $ts1 = "";
  8344. my $ts2 = "";
  8345. $project = "\l@$proj[0]";
  8346. my $header = "\n---------------- \U$project\n";
  8347. #
  8348. # skip this project if the user negated it on the cmd line
  8349. #
  8350. $main::UserArgs =~ /~$project / and next;
  8351. #
  8352. # get path to SD.INI, make sure we have it, and cd there
  8353. #
  8354. $fpr = $main::SDXRoot . "\\" . @$proj[1];
  8355. $sdini = $fpr . "\\sd.ini";
  8356. (-e $sdini) or (print "$header\nCan't find $sdini.\n" and next);
  8357. chdir $fpr or die("\nCan't cd to $fpr.\n");
  8358. #
  8359. # ts1, ts2 depend on build type
  8360. #
  8361. ($type eq "BETA") and ($ts1, $ts2, $header) = SDX::GetBetaTimestamps($buildnum, $branch, $project, $header);
  8362. ($type eq "IDX") and ($ts1, $ts2, $header) = SDX::GetIDXTimestamps($buildnum, $branch, $project, $header);
  8363. ($type eq "MAIN") and ($ts1, $ts2, $header) = SDX::GetMainTimestamps($buildnum, $branch, $project, $header);
  8364. $ts1 = "\@$ts1";
  8365. $ts2 = ($type eq "IDX" and $ts2 eq "CURRENT") ? "" : "\@$ts2";
  8366. #
  8367. # list changes
  8368. #
  8369. my $spec = "//depot/$branch/$project/...$ts1,$ts2";
  8370. my $cmd = "sd.exe changes $spec 2>&1";
  8371. $header .= "Getting changes for $spec\n\n";
  8372. SDX::RunSDCmd($header, $cmd);
  8373. }
  8374. }
  8375. # _____________________________________________________________________________
  8376. #
  8377. # GetMainTimestamps
  8378. #
  8379. # Parameters:
  8380. #
  8381. # Output:
  8382. # _____________________________________________________________________________
  8383. sub GetMainTimestamps
  8384. {
  8385. my $buildnum = $_[0];
  8386. my $branch = $_[1];
  8387. my $project = $_[2];
  8388. my $header = $_[3];
  8389. my %bh = %main::BuildHistory;
  8390. my @ts = (); my $ts1 = ""; my $ts2 = ""; my $op = "";
  8391. =begin comment text
  8392. to trace integration records:
  8393. build contrib
  8394. build type op branch branch project change/timestamp
  8395. ----- ---- --- ------ ------- ---------- -------------------------
  8396. 2268 MAIN RI main lab07_n admin 15654 2000/09/08:17:00:04
  8397. 2268 MAIN RI main lab07_n base 10928 2000/09/08:17:00:21
  8398. 2268 MAIN RI main lab07_n com 1755 2000/09/08:17:00:29
  8399. 2268 MAIN RI main lab07_n ds 4124 2000/09/08:17:00:54
  8400. 2268 MAIN RI main lab07_n enduser 19639 2000/09/08:17:00:59
  8401. 2268 MAIN RI main lab07_n inetsrv 1503 2000/09/08:17:01:23
  8402. 2268 MAIN RI main lab07_n root 25483 2000/09/08:17:02:06
  8403. in Admin
  8404. sd describe -s 15654
  8405. for each file in the RI
  8406. sd changes //depot/lab07_n/admin/path/to/file.ext@ts1,@ts2
  8407. throw away data prior to ts1
  8408. push "change" lines ont list
  8409. sort, unique
  8410. print
  8411. [\\JEFFMCD5 E:\nt\admin] sd describe -s 15654 | qgrep -e integrate | awk "{print \"sd changes \"$2\"@2000/08/0
  8412. 3:17:15:40,@2000/09/08:17:00:04\"}" | sed "s/#[0-9]+//g" | sed "s/\/main\//\/lab07_n\//g" | cmd.exe >>15654
  8413. [\\JEFFMCD5 E:\nt\admin] g Change 15654 | unique | sort /R
  8414. =end comment text
  8415. =cut
  8416. #
  8417. # main branch timestamps
  8418. #
  8419. ($branch eq "main") and do
  8420. {
  8421. #
  8422. # ts1 =
  8423. #
  8424. # time of most recent event in Main (RI checkin, or integration to IDX/Beta branch)
  8425. # for the build prior to the build in question
  8426. # in //depot/main/$project
  8427. # for all branches that contributed
  8428. #
  8429. # if no data for $project, default to Root
  8430. #
  8431. my $build = $buildnum - 1;
  8432. my $p = $project;
  8433. ($ts1, $op) = SDX::GetMainTS1($build, $p);
  8434. (!$ts1) and do
  8435. {
  8436. $p = "root";
  8437. ($ts1, $op) = SDX::GetMainTS1($build, $p);
  8438. };
  8439. $main::V2 and $header .= "ts1 = $build $branch $p $op = $ts1\n";
  8440. #
  8441. # ts2 =
  8442. #
  8443. # time of event in Main (initial RI checkin if RI/IDX, or initial integration if BETA)
  8444. # for the build following the build in question
  8445. # in //depot/main/$project
  8446. # for all branches that contributed
  8447. # less five minutes
  8448. # OR
  8449. #
  8450. # time of final RI checkin
  8451. # for the build in question
  8452. # for all branches that contributed
  8453. #
  8454. # if no data for $project, default to Root
  8455. #
  8456. @ts = ();
  8457. $build = $buildnum + 1;
  8458. $p = $project;
  8459. ($ts2, $op) = SDX::GetMainTS2($build, $p);
  8460. (!$ts2) and do
  8461. {
  8462. $p = "root";
  8463. ($ts2, $op) = SDX::GetMainTS2($build, $p);
  8464. };
  8465. #
  8466. # subtract 5 minutes if not using current build
  8467. #
  8468. ($build != $buildnum) and $ts2 = SDX::IncrDecrTS($ts2, 0, -5, 0);
  8469. $main::V2 and $header .= "ts2 = $build $branch $p $op = $ts2\n";
  8470. };
  8471. #
  8472. # lab branch timestamps
  8473. #
  8474. ($branch =~ /lab/) and do
  8475. {
  8476. my @builds = sort keys %bh; my $first = @builds[0];
  8477. my $p = $project;
  8478. #
  8479. # ts1 = time of last RI checkin of this VBL into Main
  8480. #
  8481. # default to current build Root RI time, less 10 min, if no data
  8482. #
  8483. for ($prev = $buildnum - 1; $prev > $first; $prev--)
  8484. {
  8485. (exists($bh{$prev}{main}{$branch}{$p})) and do
  8486. {
  8487. push @ts, $bh{$prev}{main}{$branch}{$p}[1];
  8488. last;
  8489. };
  8490. }
  8491. @ts = reverse sort @ts;
  8492. @ts and $ts1 = @ts[0];
  8493. (!$ts1) and do
  8494. {
  8495. $p = "root"; $prev = $buildnum;
  8496. @ts = @{$bh{$buildnum}{main}{$branch}{$p}};
  8497. $ts1 = @ts[$#ts];
  8498. $ts1 = SDX::IncrDecrTS($ts1, 0, -10, 0);
  8499. };
  8500. $main::V2 and $header .= "ts1 = $prev $branch $p RI = $ts1\n";
  8501. #
  8502. # ts2 = time of final RI checkin for this VBL into Main
  8503. #
  8504. # default to Root if no data for this project
  8505. #
  8506. $p = $project;
  8507. @ts = @{$bh{$buildnum}{main}{$branch}{$p}};
  8508. $ts2 = @ts[$#ts];
  8509. (!$ts2) and do
  8510. {
  8511. $p = "root";
  8512. @ts = @{$bh{$buildnum}{main}{$branch}{$p}};
  8513. $ts2 = @ts[$#ts];
  8514. };
  8515. $main::V2 and $header .= "ts2 = $buildnum $branch $p RI = $ts2\n";
  8516. };
  8517. (!$main::V2 and !($ts1 and $ts2)) and do
  8518. {
  8519. my $ts = !$ts1 ? "ts1" : "ts2";
  8520. die("\n\nGetMainTimestamps: missing $ts for $buildnum $branch $project.\n");
  8521. };
  8522. return ($ts1, $ts2, $header);
  8523. }
  8524. # _____________________________________________________________________________
  8525. #
  8526. # GetMainTS1
  8527. #
  8528. # Parameters:
  8529. #
  8530. # Output:
  8531. # _____________________________________________________________________________
  8532. sub GetMainTS1
  8533. {
  8534. my $build = $_[0];
  8535. my $project = $_[1];
  8536. my %bh = %main::BuildHistory;
  8537. my $bt = ""; my $op = ""; my @ts = ();
  8538. #
  8539. # return if no data for this build
  8540. #
  8541. (!($bt = $bh{$build}{buildtype})) and return "";
  8542. ($bt eq "MAIN") and do
  8543. {
  8544. my @labbranches = grep {/lab/} keys %main::AllBranches;
  8545. $op = "RI";
  8546. foreach (@labbranches) { (exists($bh{$build}{main}{$_}{$project})) and push @ts, $bh{$build}{main}{$_}{$project}[1]; }
  8547. };
  8548. ($bt eq "BETA") and do
  8549. {
  8550. my @betabranches = grep {/beta/} keys %main::AllBranches;
  8551. $op = "INT";
  8552. foreach (@betabranches) { (exists($bh{$build}{$_}{$_}{$project})) and push @ts, $bh{$build}{$_}{$_}{$project}[1]; }
  8553. };
  8554. ($bt eq "IDX") and do
  8555. {
  8556. my @idxbranches = grep {/idx/} keys %main::AllBranches;
  8557. $op = "INT";
  8558. foreach (@idxbranches) { (exists($bh{$build}{$_}{$_}{$project})) and push @ts, $bh{$build}{$_}{$_}{$project}[1]; }
  8559. };
  8560. #
  8561. # sort and reverse so final timestamp is first
  8562. #
  8563. @ts = reverse sort @ts;
  8564. return (@ts[0], $op);
  8565. }
  8566. # _____________________________________________________________________________
  8567. #
  8568. # GetMainTS2
  8569. #
  8570. # Parameters:
  8571. #
  8572. # Output:
  8573. # _____________________________________________________________________________
  8574. sub GetMainTS2
  8575. {
  8576. my $build = $_[0];
  8577. my $project = $_[1];
  8578. my %bh = %main::BuildHistory;
  8579. my $bt = ""; my $op = ""; my @ts = ();
  8580. #
  8581. # return if no data for this build
  8582. #
  8583. (!($bt = $bh{$build}{buildtype})) and return "";
  8584. #
  8585. # in the case of MAIN or IDX, we want the time of the blueline build
  8586. #
  8587. ($bt eq "MAIN" or $bt eq "IDX") and do
  8588. {
  8589. my @labbranches = grep {/lab/} keys %main::AllBranches;
  8590. $op = "RI";
  8591. foreach (@labbranches) { (exists($bh{$build}{main}{$_}{$project})) and push @ts, $bh{$build}{main}{$_}{$project}[$#{$bh{$build}{main}{$_}{$project}}]; }
  8592. };
  8593. ($bt eq "BETA") and do
  8594. {
  8595. my @betabranches = grep {/beta/} keys %main::AllBranches;
  8596. $op = "INT";
  8597. foreach (@betabranches) { (exists($bh{$build}{$_}{$_}{$project})) and push @ts, $bh{$build}{$_}{$_}{$project}[$#{$bh{$build}{$_}{$_}{$project}}]; }
  8598. };
  8599. #
  8600. # sort so the initial timestamp is first
  8601. # and return it
  8602. #
  8603. @ts = sort @ts;
  8604. return (@ts[0], $op);
  8605. }
  8606. # _____________________________________________________________________________
  8607. #
  8608. # GetBetaTimestamps
  8609. #
  8610. # Parameters:
  8611. #
  8612. # Output:
  8613. # _____________________________________________________________________________
  8614. sub GetBetaTimestamps
  8615. {
  8616. my $buildnum = $_[0];
  8617. my $branch = $_[1];
  8618. my $project = $_[2];
  8619. my $header = $_[3];
  8620. my %bh = %main::BuildHistory;
  8621. #
  8622. # ts1 = time of the most recent Beta build's RI to Main for this project
  8623. #
  8624. # OR
  8625. # earliest time of last full integration from Main to this branch for this project
  8626. #
  8627. my $ts1 = ""; my @ts = ();
  8628. my $prev = $buildnum - 1;
  8629. my @builds = sort keys %bh; my $first = @builds[0];
  8630. #
  8631. # look for the last build in which this project RI'd to Main
  8632. #
  8633. for ($prev = $buildnum - 1; $prev > $first; $prev--)
  8634. {
  8635. if (@ts = @{$bh{$prev}{main}{$branch}{$project}})
  8636. {
  8637. $ts1 = @ts[1];
  8638. $main::V2 and $header .= "ts1 = $prev $branch $project RI = $ts1\n";
  8639. last;
  8640. }
  8641. }
  8642. #
  8643. # otherwise find the last full integration from Main for this project
  8644. #
  8645. (!$ts1) and do
  8646. {
  8647. for ($prev = $buildnum; $prev > $first; $prev--)
  8648. {
  8649. if (@ts = @{$bh{$prev}{$branch}{$branch}{$project}})
  8650. {
  8651. $ts1 = @ts[$#ts];
  8652. $main::V2 and $header .= "ts1 = $prev $branch $project INT = $ts1\n";
  8653. last;
  8654. }
  8655. }
  8656. };
  8657. #
  8658. # ts2 = time of the final RI to Main of the build in question
  8659. #
  8660. # OR
  8661. # if no timestamp for this project, use Root's, it's close enough
  8662. #
  8663. my $p = $project;
  8664. @ts = @{$bh{$buildnum}{main}{$branch}{$project}};
  8665. my $ts2 = @ts[$#ts];
  8666. !$ts2 and do
  8667. {
  8668. $p = "root";
  8669. @ts = @{$bh{$buildnum}{main}{$branch}{$p}};
  8670. $ts2 = @ts[$#ts];
  8671. };
  8672. $main::V2 and $header .= "ts2 = $buildnum $branch $p RI = $ts2\n";
  8673. (!$main::V2 and !($ts1 and $ts2)) and do
  8674. {
  8675. my $ts = !$ts1 ? "ts1" : "ts2";
  8676. die("\n\nGetBetaTimestamps: missing $ts for $buildnum $branch $project.\n");
  8677. };
  8678. return ($ts1, $ts2, $header);
  8679. }
  8680. # _____________________________________________________________________________
  8681. #
  8682. # GetIDXTimestamps
  8683. #
  8684. # Parameters:
  8685. #
  8686. # Output:
  8687. # _____________________________________________________________________________
  8688. sub GetIDXTimestamps
  8689. {
  8690. my $buildnum = $_[0];
  8691. my $branch = $_[1];
  8692. my $project = $_[2];
  8693. my $header = $_[3];
  8694. my %bh = %main::BuildHistory;
  8695. my $prev; my $next;
  8696. my @ts = (); my $ts1 = ""; my $ts2 = "";
  8697. my @builds = sort keys %bh; my $first = @builds[0]; my $last = @builds[$#builds];
  8698. #
  8699. # ts1 = time of most recent INT from Main
  8700. # to this IDX branch
  8701. # for $project
  8702. # OR
  8703. # default to current build Root integration
  8704. #
  8705. my $p = $project;
  8706. for ($prev = $buildnum; $prev >= $first; $prev--)
  8707. {
  8708. if (@ts = @{$bh{$prev}{$branch}{$branch}{$p}})
  8709. {
  8710. $ts1 = @ts[1];
  8711. last;
  8712. }
  8713. }
  8714. (!$ts1) and do
  8715. {
  8716. $prev = $buildnum;
  8717. $p = "root";
  8718. $ts1 = @{$bh{$buildnum}{$branch}{$branch}{$p}}[1];
  8719. };
  8720. $main::V2 and $header .= "ts1 = $prev $branch $p INT = $ts1\n";
  8721. #
  8722. # ts2 = time of next full integration
  8723. # to this IDX branch
  8724. # for $project
  8725. # less 5 min,
  8726. # OR
  8727. # default to current state if no integration found
  8728. #
  8729. for ($next = $buildnum + 1; $next <= $last; $next++)
  8730. {
  8731. if (@ts = @{$bh{$next}{$branch}{$branch}{$project}})
  8732. {
  8733. $ts2 = @ts[1];
  8734. last;
  8735. }
  8736. }
  8737. if ($ts2)
  8738. {
  8739. $ts2 = SDX::IncrDecrTS($ts2, 0, -5, 0);
  8740. }
  8741. else
  8742. {
  8743. $next = $buildnum;
  8744. $ts2 = "CURRENT";
  8745. }
  8746. $main::V2 and $header .= "ts2 = $next $branch $project INT = $ts2\n";
  8747. #
  8748. # verify and return
  8749. #
  8750. (!$main::V2 and !($ts1 and $ts2)) and do
  8751. {
  8752. my $ts = !$ts1 ? "ts1" : "ts2";
  8753. die("\n\nGetIDXTimestamps: missing $ts for $buildnum $branch $project.\n");
  8754. };
  8755. return ($ts1, $ts2, $header);
  8756. }
  8757. # _____________________________________________________________________________
  8758. #
  8759. # IncrDecrTS
  8760. #
  8761. # Parameters:
  8762. #
  8763. # Output:
  8764. # _____________________________________________________________________________
  8765. sub IncrDecrTS
  8766. {
  8767. use Time::Local;
  8768. my ($ts, $dhour, $dmin, $dsec) = (@_);
  8769. (!$ts) and die("\nIncrDecrTS: null timestamp. Probably missing some build history.\n");
  8770. #
  8771. # convert delta h/m/s to seconds
  8772. #
  8773. $dhour *= 3600;
  8774. $dmin *= 60;
  8775. #
  8776. # split $ts and convert to Epoch seconds
  8777. #
  8778. my ($year, $month, $day, $hour, $min, $sec) = split(/[:\/]/, $ts);;
  8779. $month--;
  8780. my $epoch = timelocal($sec, $min, $hour, $day, $month, $year);
  8781. #
  8782. # add/sub to Epoch seconds
  8783. #
  8784. $epoch += $dhour + $dmin + $dsec;
  8785. #
  8786. # convert Epoch seconds to y/m/d/h/m/s
  8787. #
  8788. ($sec, $min, $hour, $day, $month, $year, $wday, $yday, $isdst) = localtime($epoch);
  8789. $year += 1900;
  8790. $month++;
  8791. # print "$year, $month, $day, $hour, $min, $sec [$wday, $yday, $isdst]\n";
  8792. #
  8793. # join into new $ts
  8794. #
  8795. $ts = "$year/$month/$day:$hour:$min:$sec";
  8796. return $ts;
  8797. }
  8798. # _____________________________________________________________________________
  8799. #
  8800. # GetBuildHistory
  8801. #
  8802. # Parameters:
  8803. #
  8804. # Output:
  8805. #
  8806. # A hash table and indices. Here's the output for sdx changes -b 2271
  8807. # for Root:
  8808. #
  8809. # build contrib
  8810. # build type op branch branch project change/timestamp
  8811. # ----- ---- --- ------ ------- ---------- -------------------------
  8812. # 2255 MAIN RI main lab06_n root 21432 2000/07/31:16:26:53
  8813. # 2256 MAIN RI main lab07_n root 21857 2000/08/03:17:16:27
  8814. # 2257 MAIN RI main lab01_n root 22110 2000/08/07:19:35:50 22108 2000/08/07:19:24:09
  8815. # 2258 MAIN RI main lab02_n root 22392 2000/08/09:22:36:41
  8816. # 2259 MAIN RI main lab04_n root 22581 2000/08/11:14:05:28
  8817. # 2260 MAIN RI main lab06_n root 22889 2000/08/15:16:27:53
  8818. # 2261 MAIN RI main lab03_n root 23320 2000/08/18:15:01:08
  8819. # 2262 MAIN RI main lab02_n root 23634 2000/08/22:20:57:20
  8820. # 2263 MAIN RI main lab06_n root 23779 2000/08/23:20:47:21 23778 2000/08/23:20:23:14
  8821. # 2264 IDX INT idx02 idx02 root 24368 2000/08/29:12:14:53
  8822. # 2264 IDX RI main lab01_n root 24060 2000/08/25:21:32:19
  8823. # 2265 MAIN RI main lab04_n root 24730 2000/08/31:15:05:24
  8824. # 2266 MAIN RI main lab03_n root 24901 2000/09/01:17:02:46
  8825. # 2267 IDX INT idx01 idx01 root 25433 2000/09/08:12:22:27
  8826. # 2267 IDX RI main lab02_n root 25230 2000/09/06:21:36:33
  8827. # 2268 MAIN RI main lab07_n root 25483 2000/09/08:17:02:06
  8828. # 2269 MAIN RI main lab01_n root 25714 2000/09/11:21:05:15 25710 2000/09/11:20:31:44
  8829. # 2269 MAIN RI main lab04_n root 25714 2000/09/11:21:05:15 25710 2000/09/11:20:31:44
  8830. # 2270 MAIN RI main lab06_n root 26211 2000/09/16:13:43:41
  8831. # 2271 MAIN RI main lab02_n root 26594 2000/09/19:20:21:00
  8832. # 2271 MAIN RI main lab03_n root 26602 2000/09/19:20:54:23
  8833. # 2271 MAIN RI main lab07_n root 26585 2000/09/19:19:45:39 26583 2000/09/19:19:42:38
  8834. # 2272 MAIN RI main lab01_n root 26732 2000/09/20:19:19:54
  8835. # 2272 MAIN RI main lab04_n root 26739 2000/09/20:21:05:27
  8836. # 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
  8837. # 2273 BETA RI main beta1 root 27091 2000/09/23:18:32:20
  8838. # 2274 BETA RI main beta1 root 27255 2000/09/25:22:46:33
  8839. # 2275 BETA RI main beta1 root 27365 2000/09/26:18:03:00
  8840. # 2276 BETA RI main beta1 root 27524 2000/09/27:17:25:33
  8841. # 2277 BETA RI main beta1 root 27641 2000/09/28:16:54:01
  8842. # 2278 BETA RI main beta1 root 27784 2000/09/29:17:25:06
  8843. # 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
  8844. # 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
  8845. # _____________________________________________________________________________
  8846. sub GetBuildHistory
  8847. {
  8848. my $buildnum = $_[0];
  8849. my %bh = ();
  8850. my %br = ();
  8851. my $sdchanges = "sd.exe changes -m 500";
  8852. $main::BuildBranches = ();
  8853. $main::AllBranches = ();
  8854. #
  8855. # do a quick check in Main for RI/Int'n changes and bail
  8856. # if no data for this build
  8857. #
  8858. chdir $main::SDXRoot;
  8859. (!(grep {/ $main::BuildNumber /} grep {/'(RI|INT)[:]*/} `$sdchanges //depot/main/...`)) and do
  8860. {
  8861. print "\nNo build history for $main::BuildNumber found in RI/integration change comments.\n";
  8862. return 0;
  8863. };
  8864. print "\nGetting build history...";
  8865. foreach $proj (@main::SDMapProjects)
  8866. {
  8867. my $project = "\l@$proj[0]";
  8868. my $header = "\n---------------- \U$project\n";
  8869. #
  8870. # skip this project if the user negated it on the cmd line
  8871. #
  8872. $main::UserArgs =~ /~$project / and next;
  8873. #
  8874. # get path to SD.INI, make sure we have it, and cd there
  8875. #
  8876. $fpr = $main::SDXRoot . "\\" . @$proj[1];
  8877. $sdini = $fpr . "\\sd.ini";
  8878. (-e $sdini) or (print "$header\nCan't find $sdini.\n" and next);
  8879. chdir $fpr or die("\nCan't cd to $fpr.\n");
  8880. $main::V3 and print $header;
  8881. print "\n $project";
  8882. =begin comment text
  8883. # use this to fix change comments missing ri/i records:
  8884. my @main = grep {/$main::BuildNumber/i} `$sdchanges //depot/main/$project/...`;
  8885. foreach (@main)
  8886. {
  8887. $ch = (split(/ /, $_))[1];
  8888. print "\n$ch: $_";
  8889. system "sd.exe change -f $ch";
  8890. }
  8891. next;
  8892. =end comment text
  8893. =cut
  8894. #
  8895. # cast back in the major branches for integration/RI changes
  8896. #
  8897. # BUGBUG: change this to get last 500 ** from @1,@<timestamp of $main::BuildNumber> **
  8898. #
  8899. my @main = grep {/'RI[:]*/i} `$sdchanges //depot/main/$project/...`; print ".";
  8900. my @idx01 = grep {/'INT[:]*/i} `$sdchanges //depot/idx01/$project/...`; print ".";
  8901. my @idx02 = grep {/'INT[:]*/i} `$sdchanges //depot/idx02/$project/...`; print ".";
  8902. my @beta1 = grep {/'INT[:]*/i} `$sdchanges //depot/beta1/$project/...`; print ".";
  8903. #
  8904. # hash of pointers to changelist arrays
  8905. #
  8906. %main::BuildBranches = (main => \@main, idx01 => \@idx01, idx02 => \@idx02, beta1 => \@beta1, beta2 => \@beta2);
  8907. #
  8908. # populate the hash
  8909. #
  8910. # for each build branch
  8911. # for each change
  8912. # extract change number and timestamp
  8913. # extract build number
  8914. # extract branch(es)
  8915. # for each contributing lab branch
  8916. # store change number, timestamp
  8917. # also store branch names seen
  8918. # also keep track of branches affecting the build in question
  8919. #
  8920. while ($bb = each %main::BuildBranches)
  8921. {
  8922. # print ".";
  8923. foreach (@{$main::BuildBranches{$bb}})
  8924. {
  8925. $main::V3 and print "$_";
  8926. my @f = split(/ /,$_);
  8927. $change = @f[1];
  8928. $ts = "@f[3]:@f[4]";
  8929. #
  8930. # munge the comment field to get build # and branch(es) involved
  8931. #
  8932. @f = split(/'/,$_); @f = split(/ /, @f[1]);
  8933. my @bn = grep {/[0-9][0-9[0-9][0-9][,;:-]*$/} @f; $bn = @bn[0]; $bn =~ s/[,;:-]//g;
  8934. #
  8935. #$bn =~ /^(22[78][0-9]|2269)/ and next;
  8936. #print "bn = '$bn'\n";
  8937. #
  8938. # for each branch in the comment, save this changenum/ts
  8939. #
  8940. @branches = grep {/(lab|idx|beta)/i} @f;
  8941. foreach $br (@branches)
  8942. {
  8943. #
  8944. # always lowercase, and lab branches
  8945. # must end in _n
  8946. #
  8947. $br = "\l$br";
  8948. ($br =~ /lab/) and do { $br =~ s/_n//g; $br .= "_n"; };
  8949. $main::V3 and print " $bn, $bb, $br, $project = ($change $ts)\n";
  8950. push @{$bh{$bn}{$bb}{$br}{$project}}, ($change,$ts);
  8951. # store branch name
  8952. $main::AllBranches{"\l$br"} = 1;
  8953. push @{$bh{$bn}{branches}}, $br;
  8954. }
  8955. }
  8956. $main::V3 and print "\n";
  8957. }
  8958. }
  8959. print "\n\n";
  8960. #
  8961. # figure out build types
  8962. #
  8963. foreach $bn (sort keys %bh)
  8964. {
  8965. my @btb = @{$bh{$bn}{branches}};
  8966. (grep {/lab/} @btb) and $bh{$bn}{buildtype} = "MAIN";
  8967. (grep {/beta/} @btb) and $bh{$bn}{buildtype} = "BETA";
  8968. (grep {/idx/} @btb) and $bh{$bn}{buildtype} = "IDX";
  8969. }
  8970. ($main::V2) and do
  8971. {
  8972. SDX::PrintBH(\%bh, 0);
  8973. print "\n all build branches: "; foreach $br (sort keys %main::BuildBranches) { print "'$br' "; }
  8974. print "\n all lab branches: "; foreach $br (sort keys %main::AllBranches) { print "'$br' "; }
  8975. print "\n $buildnum type = '$bh{$buildnum}{buildtype}'\n";
  8976. };
  8977. %main::BuildHistory = %bh;
  8978. return 1;
  8979. }
  8980. # _____________________________________________________________________________
  8981. #
  8982. # PrintBH
  8983. #
  8984. # Parameters:
  8985. #
  8986. # Output:
  8987. # _____________________________________________________________________________
  8988. sub PrintBH
  8989. {
  8990. my ($bh, $buildnum) = @_;
  8991. print "\n";
  8992. #
  8993. # if we have a specific build number, print just its data
  8994. # else print the entire history
  8995. #
  8996. my $op = "";
  8997. my @bh2 = ();
  8998. my @builds = $buildnum ? ("$buildnum") : sort keys %$bh;
  8999. my @buildbranches = sort keys %main::BuildBranches;
  9000. my @allbranches = sort keys %main::AllBranches;
  9001. foreach $bn (@builds)
  9002. {
  9003. foreach $bb (@buildbranches)
  9004. {
  9005. foreach $br (@allbranches)
  9006. {
  9007. foreach (@main::SDMapProjects)
  9008. {
  9009. my $p = @$_[0];
  9010. $op = $bb eq "main" ? "RI" : "INT";
  9011. (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;
  9012. }
  9013. }
  9014. }
  9015. }
  9016. print " build contrib\n";
  9017. print " build type op branch branch project change/timestamp\n";
  9018. print " ----- ---- --- ------ ------- ---------- -------------------------\n";
  9019. @bh2 = sort @bh2;
  9020. foreach (@bh2) { print "$_"; }
  9021. print "\n\n";
  9022. }
  9023. # _____________________________________________________________________________
  9024. #
  9025. # GetActiveBranches
  9026. #
  9027. # Parameters:
  9028. #
  9029. # Output:
  9030. # _____________________________________________________________________________
  9031. sub GetActiveBranches
  9032. {
  9033. =begin comment text
  9034. [\\JEFFMCD5 E:\nt] sd files //depot/*/root/* | qgrep -v -e delete -e /main | sed "s/\// /g" | awk "{print $2}"
  9035. | sort | unique
  9036. beta1
  9037. idx01
  9038. idx02
  9039. Lab01_N
  9040. lab01_n-vc
  9041. Lab01_N+1
  9042. Lab02_N
  9043. Lab02_N+1
  9044. Lab03_N
  9045. Lab03_N+1
  9046. Lab04_N
  9047. Lab04_N+1
  9048. Lab06_N
  9049. Lab06_N+1
  9050. Lab07_N
  9051. Lab07_N+1
  9052. Lab21_N
  9053. =end comment text
  9054. =cut
  9055. }
  9056. # _____________________________________________________________________________
  9057. #
  9058. # VerifySubmitComment
  9059. #
  9060. # Parameters:
  9061. #
  9062. # Output:
  9063. # _____________________________________________________________________________
  9064. sub VerifySubmitComment
  9065. {
  9066. #
  9067. # if user is RI'g or integrating, standardize comment
  9068. # RI: <lab(s)> <buildnum> <user-text>
  9069. # INT: <lab(s)> <buildnum> <user-text>
  9070. #
  9071. ($main::MinusR or $main::MinusT) and do
  9072. {
  9073. my $sc = $main::SubmitComment; $sc =~ s/\+/PLUS/g;
  9074. my @f = split(/ /, $sc);
  9075. # RI:/INT:
  9076. my $op = $main::MinusR ? "RI:" : "INT:";
  9077. # branch(es)
  9078. my @branches = grep {/(lab|idx|beta)/i} @f;
  9079. if (!@branches)
  9080. {
  9081. print "\nMissing branch.\n";
  9082. print "\nSubmit comment must include the branch(es) being (reverse) integrated. Valid\n";
  9083. print "branch names are beta1, idx01, idx02, lab01_n, lab07_n+1, etc.\n";
  9084. die("\n");
  9085. }
  9086. else
  9087. {
  9088. #
  9089. # strip out redundant branch names
  9090. #
  9091. my %uniq = ();
  9092. foreach (@branches) { $uniq{$_} = 1; }
  9093. @branches = sort keys %uniq;
  9094. #
  9095. # strip name from original comment, avoid duplicates
  9096. #
  9097. foreach (@branches) { $sc =~ s/$_//g; }
  9098. #
  9099. # for bare lab branches, add _n
  9100. #
  9101. foreach (@branches) { ($_ =~ /lab[0-9][0-9]$/) and $_ .= "_n"; }
  9102. $branches = join ' ', @branches;
  9103. }
  9104. # build number
  9105. @bn = grep {/[0-9][0-9][0-9][0-9][,:;-]*/} @f; my $bn = @bn[0]; $bn =~ s/[,:;-]*//g;
  9106. if (!$bn)
  9107. {
  9108. print "\nMissing build number.\n";
  9109. print "\nSubmit comment must include the build number being (reverse) integrated.\n";
  9110. die("\n");
  9111. }
  9112. else
  9113. {
  9114. # strip buildnum from original comment
  9115. $sc =~ s/$bn//g;
  9116. }
  9117. $sc = "$op $branches $bn $sc";
  9118. $sc =~ s/PLUS/\+/g; $sc =~ s/[\t\s]+/ /g;
  9119. $main::SubmitComment = $sc;
  9120. $main::V2 and print "comment = '$main::SubmitComment'\n";
  9121. };
  9122. }
  9123. #
  9124. # if we get here, something's wrong
  9125. #
  9126. 1;