Can "secret" be the Mercurial equivalent of assume unchanged/skip worktree? - mercurial

Let's assume that I want to comment out the login verification or hardcode a password in an application, just for the personal convenience of logging in immediately while developing.
I don't want to ever commit this change and I am 100% sure that I am not going to modify the source file for other reasons.
In git I would use skip-worktree. I've seen that in Mercurial offers a "secret" phase, but that is a completely new concept for me. Can I make this a "secret" commit and be sure it will never pop-up in the official repo?

"Secret" phase treat whole changeset as secret (all commits from your confidential to tip and all next made). So you will not be able to push them to public server. You'll have to rebase them to "non-secret" branch before push, but it is annoying and vulnerable to a fateful mistake.

Related

Mercurial Workflow: Need to track file in my local working copy, but not push to "trunk"

This is my setup:
I have a main Mercurial repository (call it trunk). When I want to work on a feature, I do a clone and start working on it (usually add a bookmark as well).
I use various tools to do my work, which tend to generate convenient text files in the directory. It would be very helpful for me to track those files as well. However, I need to ensure those files do not get pushed to trunk.
In a sense, I'd like a "parallel" Mercurial repository in that directory where I can track these files.
How do people manage this? I'm open to using (stable) Mercurial extensions. Ideally, I do not want to "remember" to remove stuff before pushing to trunk.
There are two possibilities: patch queues and phases. Probably for what you want to do, phases are the less-friction approach. But there is no really "parallel" solution to my knowledge.
Have a look at hg help phases for an overview and hg phase for the command to manipulate the phase of a changeset.
To be sure you never push to trunk inadvertently, you have to make your commits "secret" by default (in your HOME/.hgrc):
[phases]
new-commit = secret
Then hg push will never allow to push anything by default, you would have to selectively change the phase of the changesets you want to push.
You could also not use the above configuration and use the --secret option of hg commit when committing something you want to keep for you, but it is too risky to forget.
Note that, both with patch queues and phases, you have to be proficient with history rewriting with hg histedit, to reshuffle around the commits.

Mercurial: Pull changes from remote repository without public phase (non-publishing server, "abort: can't rebase immutable changeset")

Background
Mercurial now has Phases which are a great mechanism to keep people from altering history that should not be altered. When a changeset is pushed to remote repository it is made public and can no longer be rebased. This is normally a good thing, if the repository is public and you don't want others altering your changesets.
However, if you have your own temporary repository for sharing draft changesets only with yourself, it can get very annoying. Mercurial has a option to turn this off. Adding this to the .hg/hgrc file of the remote repository.
[phases]
publish = False
This will prevent changesets pushed to the remote repository from moving from draft phase to public phase (both the local changeset and the one just pushed to the remote repository. However, pulling this changeset down still will always pulls it down in the public phase.
Question
I am hoping to pull down changesets in the draft phase. I simply want to push a changeset to my personal server then pull it down at home. After I pull it I will rebase my temporary commit on top of any commits that I have pulled down from our true publishing server.
Any way to avoid the auto-moving of a pulled changeset to public would be great. This remote repository is a complete and total draft server for myself. Being forced to manually move the changesets back to draft after an unsuccessful rebase attempt is really starting to wear on the nerves.
References
https://www.mercurial-scm.org/wiki/Phases
Introduction to Mercurial Phases
How do I tell (locally) mercurial that a server is non-publishing?
After pushing to a review repository, "abort: can't rebase immutable changeset" on rebase
That seems like a bug. What version of Mercurial are you using? Have you tried filing a bug at https://bz.mercurial-scm.org ?
I got this resolved through help on Bugzilla. Here is a snippet of my final post there (thanks for putting me on the right track djc).
It looks like we can chalk it up to User Error/Bad Test Cases (of
course). If there is anyone to blame (besides myself) it could be
TortoiseHg. My test cases consisted of stripping commits and from one
of the two repositories and then changing the phase of that commit in
the other repository and push/pull again. It seems like TortoiseHg
would pull in the wrong phase sometimes (possibly a caching issue). I
can still reproduce this when I switch my server back and forth
between publishing and non-publishing (but not quite as consistently
before).
However, doing a command line pull seems to get it working every time.
I was using command line to check outgoing/incoming, do the phase
changes and such, but possibly never used it for the actual pull.
Sorry to waste everybody's time. I resolved it as invalid, not sure if
someone wants to change it to a better category. Let me know if there
is anything else you want me to check or expand upon.
I'll edit in any updates, let me know if anyone is still having trouble with this.

Mercurial: what are the consequences of changing a phase?

In Mercurial, the phase of a revision can be changed arbitrarily. What are the consequences of a phase change for all possible transitions (public, draft, secret) x (public, draft, secret)? Which phase changes are safe? Which may cause troubles and which kind of troubles? Which are more or less no-ops?
The default phase for a commit is draft, that's how they were treated when the phases didn't exist. When pushing a draft changeset, mercurial automatically changes its phase to public. You can use it to know which changesets you have already published or not.
But the real issue is that when the changeset is in public phase, mercurial won't let you change them with history editing extensions (like mq, rebase, etc). That's really important, because the history editing happens only in the local repository, they don't propagate with pull/push operations. So, once a changeset is published, it's out of control, it's dangerous to change it.
You can change from any phase to any other phase. The "normal flow" is to move to a higher phase (secret->draft->public), but Mercurial allows the change to a lower phase with the --force option. A phase change alone is harmless. For example, the only thing that happens when moving from public to draft or secret is that the protection of history editing is dropped, nothing else, pull and push will still work normally, Mercurial could never be confused about the changesets because they have unique identifiers. The history editing action that takes place after a phase change like this is what can cause problems. And that's why Mercurial gives the warning in the phase change and requires the --force option, as a confirmation that that's what you really want.
In general published commits shoudn't be modified, that's what the phases try to ensure. But maybe you do have control over all repositories. Or maybe you pushed something and you know that no one else pulled it yet. Whatever is the reason, you have the option of forcing the phase of the changesets back to draft and edit them. But this edition must be done in every repository that has the changesets.
A public revision can't be edited with history-editing tools (i.e. mq, rebase).
A secret revision can't be pushed to another repository (it will be ignored when you give the push command, or when another repository attempts to pull).
A draft revision allows both, but will automatically change to public if it gets pushed to another repository.
The purpose of the phase system is to prevent you from modifying a revision after you've pushed it to another repository, which is a bad idea unless you're able to delete the old version of the revision from all repositories that it's been pushed to.
All phase changes are more or less no-ops; it's just a marker to indicate what is or isn't safe to do with a revision.

Mercurial pre-push hook scanning the working copy

I need to setup a hook on a repository where people can push, that would run some validation (the goal is to reject the push if validation fails). I already have some hooks setup to auto-update after a successful push, and prevent multiple heads.
I have no problem writing a validation script (for example a shell script that runs unit tests), but it needs to run on the full working copy.
My problem is that, if I just put it in a pretxnchangegroup hook, it does not operate on updated files. If I try to hg update inside the hook, this leads to repository corruption whenever validation fails and the push is rollbacked.
My current solution is to clone the repository to some temporary folder and run the actual validation there. But I find this a bit ugly, and it is less efficient that an in-place validation doing just updates. Is this kind of hook possible to setup ?
There are ways to do this, but before I start, are you sure you want to do this? Doing blocking, maybe-slow, push-rejecting changes in a hook annoys the hell out of people, and it holds the repository writelock the whole time, so no one else can be pushing while the validation script is running. One can pretty easy toss half the productivity advantages of a DVCS out the window in an attempt to gain a little control.
You could avoid most of those disadvantages with a two-tier repository setup. Something like project-push where people can push w/o passing validation and project-pull that only has changesets which passed some validation. Then you have an out-of-band (cron or hook triggered) script that moves changesets from project-push to project-pull only after validation is confirmed. Because that test is done out of band pushes aren't blocked but non-validating changesets never make it into project-pull. You can have it email the author when their push threw project-pull into a non-validating state. Users with their .hg/hgrc configured like this wouldn't have to think about their being two repositories at all:
[paths]
default=http://host//path/to/project-pull
default-push=http://host//path/to/project-push
They could just use hg push and hg pull and things would "just work".
That said if your validation doesn't need access to all the updated files at the same time you can do your test with something like this in an external pretxnchangegroup hook:
for thefile in $(hg manifest -r tip) ; do
if ! hg cat -r tip $thefile | ./validate_on_file.sh ; then
exit
fi
done
If you do need to operate on all the files at once (compiling, etc.) and you're not willing to do a two-repo structure that frees people to push quickly, then you do need a separate repo for testing, but you don't have to clone/create it each time. Something like this in a pretxnchangegroup hook should do:
hg push /scratch/long-lived-testrepo ## Warning: may not work,
## if pretxnchangegroup locks the repo and
## blocks this push to testrepo
hg -R /scratch/long-lived-testrepo update
cd /scratch/long-lived-testrepo
./validation.sh

Enforce mercurial commit message policies via pretxnchangegroup?

As described in: http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html I thought I could write a small hook which rejects checkins with malformed commit messages. Thats no problem, the issue I encounter is the following work flow:
If a developer makes let's say 10 local commits, some of them are malformed, and then pushes them to the central repository all will be rejected, but he is unable to edit the old commit messages since rollback will work only once..
How do you solve this?
Using the HistEdit extension, you can change the commit message locally, then push back the whole changes in the main repository.
I suppose you can't mandate developers to use the same precommit hook to check commit messages, because it's not a centrally-managed project?
An alternative to #gizmo's answer is to let developers use MQ and mandate code review before pushing (or better, someone pulling from them). Then if reviewers (or some review scripts) spot the malformed messages, the developer can use qrefresh to change the message.
You need to be careful about a couple of things in that workflow, though:
NEVER EVER push/pull unfinished patch, even though qfinish does not change the hash. It's just too easy to screw up.
Make sure developer qcommit every time before sending things out for review, otherwise you won't know if s/he slips in other changes in the next iteration (not that s/he would, but s/he could).