1
votes

Consider the following situation:

$ md repo1; cd repo1
$ echo some data > myfile
$ hg init; hg addremove; hg commit -m "First commit."
adding myfile
myfile
committed changeset 0:32c7aa047f3b
$ hg serve
listening at http://vostro.rath.org:8000/ (bound to *:8000)

And then in another terminal:

$ hg clone http://vostro.rath.org:8000/ repo2
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
updating to branch default
resolving manifests
getting myfile
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

$ cd repo2; hg phase tip
0: public

..and in the first terminal again:

127.0.0.1 - - [25/May/2013 16:38:40] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
^Cinterrupted!
$ hg phase tip
0: draft

To me this looks very wrong. Someone just pulled the changeset from the first repository, so it is obviously public. However, it still appears as "draft" in the repository.

Can someone explain the rationale for this behavior? As the owner of the first repository, I would very much like to know when someone has pulled a revision (so that e.g. I don't rebase it anymore), so I think it would be sensible if the hg server process would update the phase accordingly.

3

3 Answers

4
votes

You will probably get a better answer on the mailing list for this, but my understanding is this:

hg pull has always been a read-only command and can be run without write access to the remote repository. Changing the phase in the remote repository would (obviously) require a write. On the other hand, hg push has always written to the remote repository, and so phases introduced no change.

Changing hg pull from read-only to read-write could cause some people's work flows to break, and that's a mortal sin in mercurial development. (E.g. An anonymous user pulling from a public server, sending back changes via e-mail bundles)

Basically it's a historical quirk because phases are a retro-fit.

The hole this leaves open is that the original owner of the change-set could amend it, without realising that the change has already gone into the wild. I expect that this hole hasn't worried too many people because the "change-set evolution" features that are being developed solve the problem in a better way.

I tend to think of the phases as:

  • Public - Publicly visible and immutable
  • Draft - Publicly visible and mutable
  • Secret - Not publicly visible and mutable

I think draft is only there because that's basically where we were before phases were added, and is a bit of a weak concept. Really, if your working in an environment where people may pull directly from you, then I suggest working more with public and secret phases, and avoid draft.

2
votes

As @zerkms said, pull isn't intended to change the remote repository.

If your working repository is being used as a server, you have a few options:

  • Set the default of commits to "public" instead of "draft". Others can pull at any time so just assume they are public.
  • Set the default of commits to "secret". Others won't be able to pull them. Set them to "public" when you are ready to share.
  • Set your repository as "non-publishing". Others can pull your draft changesets, but they will still be marked as "draft".

Here's how to specify these behaviors in mercurial.ini/hgrc.

[phases]
publish = False
new-commit = public
1
votes

pull isn't intended to change the remote repository phase but the phase of your local repository.

And to be clear - you shouldn't care what phase is in the remote repository.

And even more - remote repository may be hosted using old mercurial version which doesn't support phases.

Why this behavior?

Because phases are only make sense for the local repository and made to help preventing history modification mistakes.