[27sep07: To coordinate a TW undo and hg rollback, lock the gate, disable the bridge, do the undo, do a manual rollback (verify tip first), enable the bridge, rollback /export/gate-hg on the gate machine (verify tip first, and su to daemon), unlock the gate. (16:34:17) stevel: to disable the bridge, uncomment the two lines at the top of /ws/onnv-gate/public/gate/bin/sync_hg For the manual rollback, logon to the app server, go to the correct path (/hg/...), utter hg rollback && hg revert -a --no-backup or "hg update -C" instead of the "hg revert". (Is "hg revert" faster?) hg rollback && hg update -C The manual method is because we haven't tested undo support in the bridge. (Which is because we were trying to avoid any further undoes.) And I'm not sure the bridge undo code deals with /export/gate-hg. Announce on opensolaris-code & tools-discuss. -mdk] [17oct07: "hg revert" doesn't handle new files correctly. -mdk] Teamware/Mercurial Bridge TOI ============================= Basically the bridge consists of multiple parts: a) bridge.pl Takes one Teamware putback and bridges it to another SCM b) The "other SCM" stubs (Mercurial & Subversion exist, though the Subversion stubs haven't been tested in ages) c) scripts to call bridge.pl looping over each putback in onnv-gate's history /ws/onnv-gate/public/gate/bin/sync_hg is the script that's called per putback with the path to the onnv-gate public log diffs being the first (and only) argument passed to it (e.g. /ws/onnv-gate/public/log/2007/09/01.foo). If the putback was an undo, then the string "undo" is the first argument passed instead. From that script you can see it passes through to bridge.pl, passing it the path (-p) to the public diff given, the Teamware workspace (-t, i.e. /ws/onnv-gate), the open target-SCM workspace (-o, i.e. $GATE), the closed target-SCM workspace (-c, i.e. $CLOSED), and the target-SCM stub routines (i.e. changeset_hg_split.pl) Currently there are a few target-SCM stub files: changeset_hg.pl Routines for Mercurial that don't support a split gate. I started doing this to try and support non-ON workspaces. changeset_hg_split.pl Routines for Mercurial that support the split gate. This is the one you want to use for ON. changeset_analretentive.pl The *original* version of changeset_hg_split which tried to do some trickiness for handling s. files which actually failed in a corner case, but was occasionally faster. This has more or less been obsoleted for changeset_hg_split.pl which takes a dumber/naive approach but which seems to work more accurately (but is thus slower) changeset_stubs.pl Stub functions which do nothing other than print what it's doing to stdout. Used for testing. changeset_svn.pl My original routines before we had decided on Mercurial. Not tested recently, and almost certainly not working. on/changeset_phase1.pl on/changeset_phase2.pl on/changeset_phase3.pl These are three phases of stubs we need to post-process onnv-gate's history and attempt to rebuild history. These do things like walk through the history and figure out which files are moved in the future, (e.g. through things like driver renames, or the split tree putback), and does phase specific things: phase1: sets up the workspace & tree with no SCM specific operations (i.e. makes dirs, etc.) phase2: builds the rename table of future renames and where files ultimately should end up in the split tree world. phase3: derived from changeset_hg.pl, but I forget how - sorry :( move_future_renames.pl used in the rebuilding of past ONNV history - it takes the rename table generated by phase2 and rejiggers all the files so they end up in the appropriate place. How the bridge works ==================== bridge.pl is pretty naive. It parses the putback diffs path given to it, and does a few things. It parses the header to determine the author, putback comments, and files changed (thus it uses the putback comments as the changeset comment, rather than putting them together from the SCCS delta comments). For each file changed by the putback, it parses the action done to it (update, delete, create, rename, etc.) and puts the file onto an action-specific list. It then parses the actual diffs to attempt to build per-file diffs in memory of each file changed (since using gpatch is much faster than actual SCCS operations). Once those are done, it processes deletes using do_delete which is just a wrapper around 'hg remove'. Secondly, it processes renames using do_rename. do_rename has to be tricky since renames could cross repository boundaries (e.g. moving files from usr/closed to usr/src or vice versa). Its possible that a file can be renamed but the 'rename from' path doesn't exist (e.g. a file being resurrected from deleted_files). For this case, it fakes it as a create using the actual SCCS revision. If the file crosses boundaries, it copies the file across to the new repo, and 'hg rm's it from one, and 'hg add's it to the new repo. Lastly it processes creates/updates: for each file updated/created, it attempts to open the SCCS file and parse the deltas & delta metadata. If we don't have correct diff information, or if the diff information doesn't exist (i.e. a new file being created), then we call do_update (from the target-SCM) routine with no diff passed. Otherwise we call do_update with the diff. do_update (from changeset_hg_split.pl), if given a diff will attempt to apply that diff with gpatch. For this case, it merely applies it and is done with it. if it wasn't given a diff, or for some reason can't use the diff (i.e.: if it was previously renamed), then we basically do the SCCS get to retrieve the new revision and plop it on top of the file in place as the "update". After it's done processing all the actions, it basically calls the do_commit which is just a pass through to issue 'hg commit' for the open & closed repositories.