perforce gateway

Steve Borho steve at borho.org
Thu Dec 17 04:04:38 UTC 2009


On Tue, Dec 15, 2009 at 11:49 PM, Frank A. Kingswood
<frank at kingswood-consulting.co.uk> wrote:
> Steve Borho wrote:
>>>
>>> In which P4 context ("client spec") is this being done? The user only has
>>> a
>>> hg repository, right? And the gateway repository created by 'hg convert'
>>> is
>>> also not a P4 workarea.
>>
>> Ah, this is a good question.  I've been using a p4 conversion script
>> for a few years now that works right out of a p4 client.  It
>> incrementally checks out each p4 changelist and checks it into
>> Mercurial.  Brute-force but it works.  I have not used the p4 support
>> in the convert extension yet.
>
> Right, so you have a P4 workarea that is also at the same time a Mercurial
> repository. I find this gives a lot of trouble with read-only files.
>
>> This gateway would not work for every p4 setup, that's for sure.  I
>> thought about doing this entirely on the client side.  Instead of
>> doing the merge on the gateway box, an extension on the user machine
>> would allow you to "push" to a local p4 client.  Something like this:
>>
>> [p4push]
>> client = myclient
>> server = server:port
>>
>> [paths]
>> default = http://p4mirror/hg/repo
>> default-push = p4://path/to/p4client/
>>
>> The extension would monkey-patch 'push' and 'outgoing' and look for
>> p4:// urls, isolate the outgoing changesets, and then apply those
>> changes to the specified client as above and simply leave them there
>> for the user to commit (using whatever message they like).
>
> Yes, this is tempting. The user could still fold changes together if he uses
> MQ to do it, and could push several changesets to P4 in one go.
>
> But I think it would probably not work quite like you describe, because of
> course in P4 you can not have multiple pending changelists that affect the
> same files, so leaving all changes pending would fail. I think this may not
> be a problem in such a workflow because the user could polish (to whatever
> extent he wants) the changesets until they're good to go into P4 using MQ.

I didn't intend to push each changeset to p4 as a separate changelist.
 I only meant to apply the accumulated changes to the user's p4
client, for them to commit manually.  We could write the folded commit
messages to a file for them to paste into the p4 commit tool.

I'm not very interested in preserving each hg changeset in p4 as a
changelist.  For one, it's impossible to do this reliably, as other
users can commit changes in between yours, causing you to do new
merges on the mercurial side to get ready for the next p4 commit.

Perhaps this turns Mercurial into a glorified patch generation tool,
but it still beats the hell out of using p4 straight up.

> IMHO the P4 URI would probably look more like
>        default-push = p4://server:1666/client-spec-name
> because everything else can be determined from the client spec.

Sure.

> A detail that the user must not overlook in this case is that his client
> spec must match the client spec that was used to generate the hg repository
> in the first place. I suppose that hg convert could drop a .p4config file in
> the converted repository to help.

I think I would recommend the user push to the same p4 client that
they convert from.  I'll have to try this work flow for a while to see
how it feels.

>> However, this doesn't record the 'push' commit in p4 as a merge of any
>> kind on the mercurial side, so the user would have dangling hg heads
>> after each push.   In the end, the gateway approach seemed cleaner.
>
> Doing it all in the client looks really clean. It solves the client-spec
> issue, for example. All that is missing is adding the Hg revision ids to the
> P4 log message, right?

It's probably not necessary if this is all client side.  The user will
see their converted p4 changelist when they do their next incremental
conversion and can do a NULL merge between that changeset and their
development branch.

So the work flow looks like:

1 do (approximately) a day's worth of commits, or until a feature is done
2 run your convert script to pull in all new p4 changes
3 merge your branch with those p4 changes
4 "push" your accumulated work to your p4 client, commit with a
meaningful message
5 run your convert script again
6 merge with the new p4 head (accept p4 head's contents, aka internal:other)

The 'push' command will have to ensure the user's p4 client has the
same changelist checked out as the tip p4 revision in their repo.

I like this because it minimizes the number of parts that can break.
Intervening commits can not cause silent breakage.  Either your p4
commit is allowed or it isn't. If p4 rejects the commit because
someone else has modified your files, you revert your p4 client spec
and then repeat steps 2..4.

Looking at it like this, the 'push' is really 'p4import < hg diff p4trunk:tip'

--
Steve Borho



More information about the Mercurial mailing list