Patchwork commit: add --extra argument to set extra user fields

login
register
mail settings
Submitter Angel Ezquerra
Date March 6, 2014, 7:59 a.m.
Message ID <CAMefLFHcrVbMoNN592WxYpRcKuQw69q0k4hNFZLqkkafFM+dcg@mail.gmail.com>
Download mbox | patch
Permalink /patch/3870/
State Rejected
Headers show

Comments

Angel Ezquerra - March 6, 2014, 7:59 a.m.
On Thu, Mar 6, 2014 at 5:06 AM, Matt Mackall <mpm@selenic.com> wrote:
> On Wed, 2014-03-05 at 23:32 +0100, Angel Ezquerra wrote:
>> # HG changeset patch
>> # User Angel Ezquerra <angel.ezquerra@gmail.com>
>> # Date 1394000996 -3600
>> #      Wed Mar 05 07:29:56 2014 +0100
>> # Node ID 1658e55e8c9e2518236aeb8e7d1d89a1714b6f37
>> # Parent  779ceb84f4f782d32dfe47f6684107c08d2f6142
>> commit: add --extra argument to set extra user fields
>
> Perhaps the most positive thing I can say about this feature is that I
> can't stop you from doing this in a third-party extension. I'm
> definitely opposed to giving users access to putting arbitrary things in
> extra, or doing anything that's even suggestive of functionality like
> svn props. We already have enough problems managing our internal extra
> fields.

I have used subversion, but never used svn props. Could you give me a
bit more details explaining why you think this is such a bad idea? I'm
trying to create a mercurial-TFS bridge and this seemed a very
convenient way to "link" mercurial revisions with TFS changeset
numbers (for example it would let us look for a particular TFS
changest in the mercurial history). However, if you really think that
this is a terrible idea maybe I need to rethink my approach.

Assuming that this is not such a good idea, I could write an extension
as you say. However I think that I would basically need to rewrite
commands.commit, because there is no way to pass an 'extra' optional
argument to commands.commit (AFAIK). This is a bit inconvenient and a
bit risky since I would need to keep up with changes to
commands.commit if I want my extension to fully replicate the regular
behavior of the commit command. A solution would be to change
commands.commit as follows:

This would avoid advertising this capability to regular users, but
extension writers could still set the extra field if they needed to.

Would you be OK with a limited patch that did just that? I'm not
trying to push this if you are really against this. I'm just trying to
find the simplest solution to our problem.

Thanks,

Angel
Mads Kiilerich - March 6, 2014, 10:42 a.m.
On 03/06/2014 08:59 AM, Angel Ezquerra wrote:
> I'm trying to create a mercurial-TFS bridge

Have you considered implementing convert source and sink for TFS?

/Mads
Angel Ezquerra - March 6, 2014, 11:20 a.m.
On Thu, Mar 6, 2014 at 11:42 AM, Mads Kiilerich <mads@kiilerich.com> wrote:
> On 03/06/2014 08:59 AM, Angel Ezquerra wrote:
>>
>> I'm trying to create a mercurial-TFS bridge
>
>
> Have you considered implementing convert source and sink for TFS?
>
> /Mads

That is something that could be done (and I may do it). However, I
don't think that lets you have a bidirectional bridge, does it? I
haven't used convert much so please correct me if I am wrong...

I think what I'm trying to make is something similar to hggit or
hgsubversion (although I have not actually used those myself, so the
similarity may only be superficial).

It is not ready yet (I will share it when it is) but what I am doing
is adding 3 new commands that let you link a mercurial repo to a TFS
workspace and pull from / push to that TFS workspace:

- tflink: Link an existing mercurial repository to an existing TFS
branch workspace. This simply stores a TFS "branch_name" to local TFS
folder relationship on a config file).

- tfpull: Gets new TFS changesets from a linked TFS branch into a
mercurial repository. These are converted into mercurial revisions
that are made on a particular branch (called TFS.TFS_BRANCH_NAME by
default).

- tfpush: take the mercurial revisions that descend from the latest
imported TFS revision and convert them into TFS changesets. This is
tricky because TFS history must be purely linear (as in SVN). This
means that we need abort if there are multiple heads for example. We
also need to detect when the history is not linear, and in that case
choose which revisions to "push" (either always taking one of the
parents or by asking the user what to do).

Currently these commands are executed by running a stand alone
"hgtf.py" script, but I may create a proper mercurial extension and
convert them into mercurial commands instead.

To "mark" imported revisions I had planned to embed the unique TFS
changeset ID in extra.user.tfs. Perhaps a better strategy is to just
add tags. I would want to avoid creating two revisions per TFS
changeset (1 regular revision + 1 tag revision) so perhaps I will try
to create all the tags on a single commit (by tagging at the end and
folding the tag commits or by automatically updating the .hgtags file
in a single go).

I have also considered adding a new type of subrepo (tfsubrepo). This
should be pretty simple I think, and very similar to the existing
svnsubrepo. The main issue I see is that this is not something that
can be easily tested with mercurial's test suite, since it requires
access to a proprietary Team Foundation Server.

Cheers,

Angel
Mads Kiilerich - March 6, 2014, 11:31 a.m.
On 03/06/2014 12:20 PM, Angel Ezquerra wrote:
> On Thu, Mar 6, 2014 at 11:42 AM, Mads Kiilerich <mads@kiilerich.com> wrote:
>> On 03/06/2014 08:59 AM, Angel Ezquerra wrote:
>>> I'm trying to create a mercurial-TFS bridge
>>
>> Have you considered implementing convert source and sink for TFS?
>>
>> /Mads
> That is something that could be done (and I may do it). However, I
> don't think that lets you have a bidirectional bridge, does it?

It does. http://selenic.com/hg/rev/2147a734dcf9 and 
http://selenic.com/hg/rev/77872b002e73 .

/Mads
Simon King - March 6, 2014, 11:35 a.m.
On Thu, Mar 6, 2014 at 11:20 AM, Angel Ezquerra
<angel.ezquerra@gmail.com> wrote:
> On Thu, Mar 6, 2014 at 11:42 AM, Mads Kiilerich <mads@kiilerich.com> wrote:
>> On 03/06/2014 08:59 AM, Angel Ezquerra wrote:
>>>
>>> I'm trying to create a mercurial-TFS bridge
>>
>>
>> Have you considered implementing convert source and sink for TFS?
>>
>> /Mads
>
> That is something that could be done (and I may do it). However, I
> don't think that lets you have a bidirectional bridge, does it? I
> haven't used convert much so please correct me if I am wrong...
>
> I think what I'm trying to make is something similar to hggit or
> hgsubversion (although I have not actually used those myself, so the
> similarity may only be superficial).
>
> It is not ready yet (I will share it when it is) but what I am doing
> is adding 3 new commands that let you link a mercurial repo to a TFS
> workspace and pull from / push to that TFS workspace:
>
> - tflink: Link an existing mercurial repository to an existing TFS
> branch workspace. This simply stores a TFS "branch_name" to local TFS
> folder relationship on a config file).
>
> - tfpull: Gets new TFS changesets from a linked TFS branch into a
> mercurial repository. These are converted into mercurial revisions
> that are made on a particular branch (called TFS.TFS_BRANCH_NAME by
> default).
>
> - tfpush: take the mercurial revisions that descend from the latest
> imported TFS revision and convert them into TFS changesets. This is
> tricky because TFS history must be purely linear (as in SVN). This
> means that we need abort if there are multiple heads for example. We
> also need to detect when the history is not linear, and in that case
> choose which revisions to "push" (either always taking one of the
> parents or by asking the user what to do).
>
> Currently these commands are executed by running a stand alone
> "hgtf.py" script, but I may create a proper mercurial extension and
> convert them into mercurial commands instead.
>
> To "mark" imported revisions I had planned to embed the unique TFS
> changeset ID in extra.user.tfs. Perhaps a better strategy is to just
> add tags. I would want to avoid creating two revisions per TFS
> changeset (1 regular revision + 1 tag revision) so perhaps I will try
> to create all the tags on a single commit (by tagging at the end and
> folding the tag commits or by automatically updating the .hgtags file
> in a single go).

Could you use local tags to avoid the extra commits? Or just have a
separate file that tracks the mapping between TFS and hg changesets?

>
> I have also considered adding a new type of subrepo (tfsubrepo). This
> should be pretty simple I think, and very similar to the existing
> svnsubrepo. The main issue I see is that this is not something that
> can be easily tested with mercurial's test suite, since it requires
> access to a proprietary Team Foundation Server.
>
Angel Ezquerra - March 6, 2014, 11:43 a.m.
On Thu, Mar 6, 2014 at 12:35 PM, Simon King <simon@simonking.org.uk> wrote:
> On Thu, Mar 6, 2014 at 11:20 AM, Angel Ezquerra
> <angel.ezquerra@gmail.com> wrote:
>> On Thu, Mar 6, 2014 at 11:42 AM, Mads Kiilerich <mads@kiilerich.com> wrote:
>>> On 03/06/2014 08:59 AM, Angel Ezquerra wrote:
>>>>
>>>> I'm trying to create a mercurial-TFS bridge
>>>
>>>
>>> Have you considered implementing convert source and sink for TFS?
>>>
>>> /Mads
>>
>> That is something that could be done (and I may do it). However, I
>> don't think that lets you have a bidirectional bridge, does it? I
>> haven't used convert much so please correct me if I am wrong...
>>
>> I think what I'm trying to make is something similar to hggit or
>> hgsubversion (although I have not actually used those myself, so the
>> similarity may only be superficial).
>>
>> It is not ready yet (I will share it when it is) but what I am doing
>> is adding 3 new commands that let you link a mercurial repo to a TFS
>> workspace and pull from / push to that TFS workspace:
>>
>> - tflink: Link an existing mercurial repository to an existing TFS
>> branch workspace. This simply stores a TFS "branch_name" to local TFS
>> folder relationship on a config file).
>>
>> - tfpull: Gets new TFS changesets from a linked TFS branch into a
>> mercurial repository. These are converted into mercurial revisions
>> that are made on a particular branch (called TFS.TFS_BRANCH_NAME by
>> default).
>>
>> - tfpush: take the mercurial revisions that descend from the latest
>> imported TFS revision and convert them into TFS changesets. This is
>> tricky because TFS history must be purely linear (as in SVN). This
>> means that we need abort if there are multiple heads for example. We
>> also need to detect when the history is not linear, and in that case
>> choose which revisions to "push" (either always taking one of the
>> parents or by asking the user what to do).
>>
>> Currently these commands are executed by running a stand alone
>> "hgtf.py" script, but I may create a proper mercurial extension and
>> convert them into mercurial commands instead.
>>
>> To "mark" imported revisions I had planned to embed the unique TFS
>> changeset ID in extra.user.tfs. Perhaps a better strategy is to just
>> add tags. I would want to avoid creating two revisions per TFS
>> changeset (1 regular revision + 1 tag revision) so perhaps I will try
>> to create all the tags on a single commit (by tagging at the end and
>> folding the tag commits or by automatically updating the .hgtags file
>> in a single go).
>
> Could you use local tags to avoid the extra commits? Or just have a
> separate file that tracks the mapping between TFS and hg changesets?

Actually I first started using a separate file inside the .hg folder
and then I changed it so that the current unfinished implementation
uses local tags, not regular tags. However I think that I must record
it "in history" so that more than one user can link its local
repository clone to their own TF workspace.

Angel
Angel Ezquerra - March 6, 2014, 11:48 a.m.
On Thu, Mar 6, 2014 at 12:31 PM, Mads Kiilerich <mads@kiilerich.com> wrote:
> On 03/06/2014 12:20 PM, Angel Ezquerra wrote:
>>
>> On Thu, Mar 6, 2014 at 11:42 AM, Mads Kiilerich <mads@kiilerich.com>
>> wrote:
>>>
>>> On 03/06/2014 08:59 AM, Angel Ezquerra wrote:
>>>>
>>>> I'm trying to create a mercurial-TFS bridge
>>>
>>>
>>> Have you considered implementing convert source and sink for TFS?
>>>
>>> /Mads
>>
>> That is something that could be done (and I may do it). However, I
>> don't think that lets you have a bidirectional bridge, does it?
>
>
> It does. http://selenic.com/hg/rev/2147a734dcf9 and
> http://selenic.com/hg/rev/77872b002e73 .
>
> /Mads

That's interesting. Thanks for the info! I'm not sure how well this
can be mapped to the work I already did, but I'll look into it.

Thanks,

Angel
Simon King - March 6, 2014, 11:54 a.m.
On Thu, Mar 6, 2014 at 11:43 AM, Angel Ezquerra
<angel.ezquerra@gmail.com> wrote:
> On Thu, Mar 6, 2014 at 12:35 PM, Simon King <simon@simonking.org.uk> wrote:
>> On Thu, Mar 6, 2014 at 11:20 AM, Angel Ezquerra
>> <angel.ezquerra@gmail.com> wrote:
>>> On Thu, Mar 6, 2014 at 11:42 AM, Mads Kiilerich <mads@kiilerich.com> wrote:
>>>> On 03/06/2014 08:59 AM, Angel Ezquerra wrote:
>>>>>
>>>>> I'm trying to create a mercurial-TFS bridge
>>>>
>>>>
>>>> Have you considered implementing convert source and sink for TFS?
>>>>
>>>> /Mads
>>>
>>> That is something that could be done (and I may do it). However, I
>>> don't think that lets you have a bidirectional bridge, does it? I
>>> haven't used convert much so please correct me if I am wrong...
>>>
>>> I think what I'm trying to make is something similar to hggit or
>>> hgsubversion (although I have not actually used those myself, so the
>>> similarity may only be superficial).
>>>
>>> It is not ready yet (I will share it when it is) but what I am doing
>>> is adding 3 new commands that let you link a mercurial repo to a TFS
>>> workspace and pull from / push to that TFS workspace:
>>>
>>> - tflink: Link an existing mercurial repository to an existing TFS
>>> branch workspace. This simply stores a TFS "branch_name" to local TFS
>>> folder relationship on a config file).
>>>
>>> - tfpull: Gets new TFS changesets from a linked TFS branch into a
>>> mercurial repository. These are converted into mercurial revisions
>>> that are made on a particular branch (called TFS.TFS_BRANCH_NAME by
>>> default).
>>>
>>> - tfpush: take the mercurial revisions that descend from the latest
>>> imported TFS revision and convert them into TFS changesets. This is
>>> tricky because TFS history must be purely linear (as in SVN). This
>>> means that we need abort if there are multiple heads for example. We
>>> also need to detect when the history is not linear, and in that case
>>> choose which revisions to "push" (either always taking one of the
>>> parents or by asking the user what to do).
>>>
>>> Currently these commands are executed by running a stand alone
>>> "hgtf.py" script, but I may create a proper mercurial extension and
>>> convert them into mercurial commands instead.
>>>
>>> To "mark" imported revisions I had planned to embed the unique TFS
>>> changeset ID in extra.user.tfs. Perhaps a better strategy is to just
>>> add tags. I would want to avoid creating two revisions per TFS
>>> changeset (1 regular revision + 1 tag revision) so perhaps I will try
>>> to create all the tags on a single commit (by tagging at the end and
>>> folding the tag commits or by automatically updating the .hgtags file
>>> in a single go).
>>
>> Could you use local tags to avoid the extra commits? Or just have a
>> separate file that tracks the mapping between TFS and hg changesets?
>
> Actually I first started using a separate file inside the .hg folder
> and then I changed it so that the current unfinished implementation
> uses local tags, not regular tags. However I think that I must record
> it "in history" so that more than one user can link its local
> repository clone to their own TF workspace.
>

Fair enough.

In answer to one of your earlier questions, about having to rewrite
commands.commit, you could avoid that with a very ugly hack, passing
the extra data in via the config object. You could even do that from
the command line:

hg ci --config tfs.changeset=xxx

You would then wrap localrepo.commit, get it to pull the data it wants
from the config and put it in the extra dict.

(As a proper solution this is horrible, but it seems like the least
invasive way to get the behaviour you want)

Simon
Angel Ezquerra - March 6, 2014, 12:42 p.m.
On Thu, Mar 6, 2014 at 12:54 PM, Simon King <simon@simonking.org.uk> wrote:
> On Thu, Mar 6, 2014 at 11:43 AM, Angel Ezquerra
> <angel.ezquerra@gmail.com> wrote:
>> On Thu, Mar 6, 2014 at 12:35 PM, Simon King <simon@simonking.org.uk> wrote:
>>> On Thu, Mar 6, 2014 at 11:20 AM, Angel Ezquerra
>>> <angel.ezquerra@gmail.com> wrote:
>>>> On Thu, Mar 6, 2014 at 11:42 AM, Mads Kiilerich <mads@kiilerich.com> wrote:
>>>>> On 03/06/2014 08:59 AM, Angel Ezquerra wrote:
>>>>>>
>>>>>> I'm trying to create a mercurial-TFS bridge
>>>>>
>>>>>
>>>>> Have you considered implementing convert source and sink for TFS?
>>>>>
>>>>> /Mads
>>>>
>>>> That is something that could be done (and I may do it). However, I
>>>> don't think that lets you have a bidirectional bridge, does it? I
>>>> haven't used convert much so please correct me if I am wrong...
>>>>
>>>> I think what I'm trying to make is something similar to hggit or
>>>> hgsubversion (although I have not actually used those myself, so the
>>>> similarity may only be superficial).
>>>>
>>>> It is not ready yet (I will share it when it is) but what I am doing
>>>> is adding 3 new commands that let you link a mercurial repo to a TFS
>>>> workspace and pull from / push to that TFS workspace:
>>>>
>>>> - tflink: Link an existing mercurial repository to an existing TFS
>>>> branch workspace. This simply stores a TFS "branch_name" to local TFS
>>>> folder relationship on a config file).
>>>>
>>>> - tfpull: Gets new TFS changesets from a linked TFS branch into a
>>>> mercurial repository. These are converted into mercurial revisions
>>>> that are made on a particular branch (called TFS.TFS_BRANCH_NAME by
>>>> default).
>>>>
>>>> - tfpush: take the mercurial revisions that descend from the latest
>>>> imported TFS revision and convert them into TFS changesets. This is
>>>> tricky because TFS history must be purely linear (as in SVN). This
>>>> means that we need abort if there are multiple heads for example. We
>>>> also need to detect when the history is not linear, and in that case
>>>> choose which revisions to "push" (either always taking one of the
>>>> parents or by asking the user what to do).
>>>>
>>>> Currently these commands are executed by running a stand alone
>>>> "hgtf.py" script, but I may create a proper mercurial extension and
>>>> convert them into mercurial commands instead.
>>>>
>>>> To "mark" imported revisions I had planned to embed the unique TFS
>>>> changeset ID in extra.user.tfs. Perhaps a better strategy is to just
>>>> add tags. I would want to avoid creating two revisions per TFS
>>>> changeset (1 regular revision + 1 tag revision) so perhaps I will try
>>>> to create all the tags on a single commit (by tagging at the end and
>>>> folding the tag commits or by automatically updating the .hgtags file
>>>> in a single go).
>>>
>>> Could you use local tags to avoid the extra commits? Or just have a
>>> separate file that tracks the mapping between TFS and hg changesets?
>>
>> Actually I first started using a separate file inside the .hg folder
>> and then I changed it so that the current unfinished implementation
>> uses local tags, not regular tags. However I think that I must record
>> it "in history" so that more than one user can link its local
>> repository clone to their own TF workspace.
>>
>
> Fair enough.
>
> In answer to one of your earlier questions, about having to rewrite
> commands.commit, you could avoid that with a very ugly hack, passing
> the extra data in via the config object. You could even do that from
> the command line:
>
> hg ci --config tfs.changeset=xxx
>
> You would then wrap localrepo.commit, get it to pull the data it wants
> from the config and put it in the extra dict.
>
> (As a proper solution this is horrible, but it seems like the least
> invasive way to get the behaviour you want)

That is neat but as you say also pretty "horrible" (in a kind of
awesome way :-) )

Angel
Matt Mackall - March 6, 2014, 7:50 p.m.
On Thu, 2014-03-06 at 08:59 +0100, Angel Ezquerra wrote:
> I'm
> trying to create a mercurial-TFS bridge and this seemed a very
> convenient way to "link" mercurial revisions with TFS changeset
> numbers (for example it would let us look for a particular TFS
> changest in the mercurial history). However, if you really think that
> this is a terrible idea maybe I need to rethink my approach.

I think this is actually a legitimate thing to want to do, but it's also
one we've always done via extensions. This naturally creates a nice,
high barrier to adding new types of metadata for Mercurial to care
about, which I consider to be a good thing.

The problem with something like extra is that it's TOO useful. It looks
vaguely like a solution to everyone's pet problem, and if we expose it
directly, everyone will abuse it. And then everyone will want to extend
it with hooks and supplementary commands and special merge behavior and
hgweb etc. etc. If we instead say "do it yourself with
a .myextrametadata file", they'll say "but that's ugly" and maybe
re-evaluate their need. At worst the ugliness will be on their plate and
not ours.

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1370,7 +1370,7 @@ 
     branch = repo[None].branch()
     bheads = repo.branchheads(branch)

-    extra = {}
+    extra = opts.get('extra', {})
     if opts.get('close_branch'):
         extra['close'] = 1