How to prevent Mercurial commits/pushes of certain files? - mercurial

At a point in our development process we send all *.resx files to a translator. The translator usually takes a week to send back the files. During this time no one is allowed to add, remove or update any resx file.
How can I configure mercurial to enforce that policy?
Our setup: Each dev works with a local clone of our central repository.
Nice to have:
I'll turn the "policy" on and off every few weeks. So ideally, I'd like something that is easy to configure at one place and that affect all devs.
I'd rather enforce that policy at the local repository level then at the central repository level because if we prevent the "push" on the central repository, it will be harder for the dev to undo the already locally committed changeset.
Thanks
UPDATE:
More info on the translation process:
Merging is not an issue here. The translator does not change the files that we sent to him. We send him a bunch of language neutral .resx (form1.resx) and returns a bunch of language specific resx (form1.FR.resx).
Why prevent adding new resx? Adding a resx occurs when we add a new UI to our application. If we do that after the translation package has been sent, the translator won't know about the new UI and we'll end up with a new UI with no translation.
Why prevent updating resx? If the dev changes a label value from "open" to "close", he has made a very important semantic change. If he does that after the translation package has been sent, we won't get the right translation back.

You cannot stop by people from committing changes to .resx files unless you have control over their desktop machines (using a pretxncommit hook), and even then it's easily bypassed. It's much more normal to put the check on the central server at time of push using a pretxnchangegroup hook, but you're right that they'll have to fix up any changesets and re-push, which is advanced usage. In either case you'd used the AclExtension to enforce the actual restriction.
Here are two alternate ways to go about this that might work out better for you:
Clone your repository at the start of the translation process, warn developers to leave .resx alone for awhile, apply the work of the translators when they're done, and then merge those changes back into the main development repository with a merge command that always gives the incoming changes priority: X . Then use a simple hg log command to find all the changes in .resx that just got overwritten and tell the developers to re-add them. Chide them at this time.
alternately
Make the .resx files a Subrepository of the larger outer repository. Then turn off write access to that resx repository during the forbidden period. Developers will be able to commit in the outer repository but not the inner one, but clones will still get both exactly as they always did.
For what it's worth, everyone else handles this problem with simple merging, .resx is (XML) text, and it merges just fine.
When working with a DVCS it's not always easy to exactly mirror your svn experience, but there's usually a better option anyway.

You could add *.resx to the hgignore file

Related

Dealing with customized local source files in Mercurial

Our team of 4 currently uses svn, but I am testing out Mercurial. We code mostly in C++ and C# on .net. I have installed TortoiseHg, and use hgsubversion to push/pull against the existing svn repo. Other developers on the team will remain on svn for now.
I tend to have a few source files that I have customized (butchered would be a better term) in some specific way that I don't want to push to other developers. But I do want these custom changes compiled into my version of the project. The ratio of normal files to customized files is about 100:1
What is the best way to deal with these butchered files in mercurial? I could simply uncheck butchered files during commits, but eventually, I will forget this step. I have taken a brief look at shelving and ignoring.
Ignoring doesn't seem right, because these are tracked files. I do want to pull changes to butchered files from others. Shelving was close, but it removes the butchered code from my working copy, so that isn't correct either.
I can't be the only code butcher out there. Let me know how you deal with this. Git users, we are happy to hear from you too, we haven't entirely committed to using hg.
If they're files most everyone will be modifying (per developer database account info, etc.) the right way to do it is by tracking a xxxxx.sample file. For example have the build script use local-database.config which is in the .hgignore and provide a local-database.config.sample file in the repository. You can either include "copy the sample to the actual" in your instructions or have the build script do it automatically if the actual doesn't already exist. We have our config do a include of settings.local if and only if it exists, and allow it to override main settings. Then no one needs a local config, but it can be optionally used to alter anything w/o a risk of committing it.
If they're files that only you will be modifying the best way is to learn Mercurial queues. Then you can pop that changeset with the you-only changes, push to central repo, and then apply it again for your builds. There are various extensions that do similar things (shelve for example), but mq is preferable because you can version the overlay you're popping and applying.

Can I work in the repository in a single user Mercurial workflow?

I use Mercurial in a single-user workflow to have the option to roll back changes if my coding or writing goes horribly wrong (I primarily use the Stata and R statistics packages and LaTeX). While working only locally, this has been easy since all I have is the main repo.
Recently I have started ssh-ing into a Linux server for more computational power. So far I have been manually copying files back and forth and using Mercurial only locally, but I would like to use Mercurial to take care of this and keep these two workflows synchronized. Also, I like the ability to code both locally (on my laptop or desktop) and on the server.
Do I need to work on a clone of the main repo on the server and keep the main repo untouched? Or can I work directly in the main repo when I am on the server? In this question #gizmo points to this workflow guide; the "single developer" discussion is helpful, but it's still not clear to me that I can work in the main repo while I'm on the server without causing some major problem that I don't yet understand.
Thanks!
Edit: I should add that I have worked through Joel Spolsky's HgInit.com tutorial and I'm comfortable pushing/pulling/cloning/etc over ssh, but I am still not sure if I can work in the main repo without causing heartache later. Or maybe this is more a philosophical question? Thanks!
Mercurial is DVCS, it means - in each location you have both: local working copy and local repository
Mercurial is DVCS, it means - you can freely exchange (pull|push) data between repos (if they provide remote-access methods).
If you
comfortable pushing/pulling/cloning/etc over ssh
and don't forget perform pull|push cycle around your work at home (in order to don't run hg serve at home-host and sync from server as source) you don't get any headache at all with perfect linear aggregated history on each place. And even you forget to sync repo sometimes, you get in worst case two heads later, which you'll be able to merge easy (doesn't know formats of Stata and R data-files, but LaTeX, as text, is mergeable)
There is no problem with working directly in the repository on your server. From Mercurial's point of view, the "main" repository is just another random repository — Mercurial doesn't consider it to be special.
You don't say this directly, but one thing that people ask is "What happens when I push to the server?" The answer is that hg push only sends data into the repository (the .hg/ folder). The working copy is not touched on the server when you push to it. Since you push new changesets to the server, you might need to run hg update the next time you work on the server. This is just like if you had run hg pull on the server — there you'll also merge or update afterwards.
I have this situation all the time: I create a repository at home and clone it to my computer at work. I change files in either location and push/pull between the two repositories. If I need to share my work with others, then I make a repository at Bitbucket and push the code there. That way Bitbucket serves as a nice canonical repository for the code and I typically change the default path to Bitbucket in the repositories at home and at work. So at home I would have:
[paths]
default = httsp://bitbucket.org/mg/<repo>/
work = ssh://mg#work/<repo>
so that I can do hg push to send things to Bitbucket and hg pull work to grab things directly from work (in case I forgot to push to Bitbucket before leaving).

What's the best way to track private files in a public Mercurial repository?

"If it’s not in source control, it doesn’t exist."
This question was addressed for Git here: Techniques to handle a private and public repository?. What about for Mercurial?
I have several public Bitbucket repos (with multiple committers) where I'd like the source to be public, but which load API, SSH keys and other sensitive info from untracked files. However this results in someone emailing around the new config file if we add a new Mailchimp or Hunch or Twilio API key. Is there a way to shield these files from public view somehow and still track them? Everyone is syncing their repo through Bitbucket.
There are two good ways to handle this (besides zerkms's solution, which doesn't offer the easy of synchronization you want, but is what I'd do anyway):
Use Mercurial Queues. When you create a mercurial queue with hg qinit --create-repo it creates an overlay system that can be qpushed atop the existing repo. So you keep your secrets in queues and qpush them when you need them, and qpop them when you don't. With --create-repo the set of overlays (patches) is handled in a repository of its own. So people in the know can push/pull the secret overlay repo and people w/o access to it can use the base repo. The patch repo can be a private repo on bitbucket or hosted elsewhere.
or
Use a subrepo exactly as described in the git solution.
Create filename.ext.sample files with templates inside (probably filled with dummy data), which need to be copied and filled with actual data in the particular working directory.
That is what I usually do ;-)
Zerkms' solution is fast, easy, and clean, and likely your best bet for preventing secure content from being tracked / published; however as you say, "If it’s not in source control, it doesn’t exist." I find that far more often what I'm trying to keep out of source control is not a security concern, but simply a configuration setting. I believe these should be tracked, and my current employer has a rather clever setup for dealing with this, which I'll attempt to simplify / generalize / summarize here.
REPOSITORY
code/
...
scripts/
configparse.sh
...
config/
common.conf
env/
development.conf
testing.conf
production.conf
users/
dimo414.conf
mycoworker.conf
...
hosts/
dimo414-laptop.conf
dimo414-server.conf
mycoworker-laptop.conf
...
local.conf*
makefile
.conf*
* untracked file
Hopefully the idea here is pretty clear, we define settings at each appropriate level, enabling highly granular control of the codebase's behavior in a logical and consistent fashion.
The scripts/configparse.sh script reads all the necessary configuration files in turn and builds .conf out of all the settings it finds.
config/common.conf is the starting point, and contains logical default values for every setting. Many will likely get overwritten, but something is specified here. It's an error for a setting to be found in another file that isn't first set in common.conf.
config/env/ controls the behavior in different environments, doing things like pointing to the correct database servers.
config/users/ looks for a $USER.conf file, useful for setting things I care about, such as increasing the logging level for aspects my team works on, or customizing behavior I prefer to use across all my machines.
config/hosts does the same for machines, looking for $HOSTNAME.conf. Useful for machine-specific settings like application paths or data directories.
config/local.conf is an untracked file, and lets you set checkout-specific values and/or content you don't want in version control.
The aggregate of all these settings is output to .conf, which is what the rest of the codebase looks for when loading settings.

mercurial temporarily ignore versioned files

My question is essentially the same as here but applies to mercurial. I have a set of files that are under version control, and one save operation changes quite a lot of files. Some of the resulting changes are important for revision control, and some of the changes are just junk. I can "partition" off the junk into separate files. These junk files need to be part of a basic checkout in order for it to work, but their contents (and changes over time) aren't that important for revision control. Right now I just tell all our developers not to commit these files, but we all forget and it creates a lot of extra baggage in the repository. I don't really like the svn solution proposed because there are quite a lot of files and I want a simple clone to just work without all this extra manual work, so I was wondering if mercurial has a better alternative. It's kind of like hg shelve but not quite, and kind of like ignore, but not quite. Is there some hg extension that allows for this? Can git do it?
Mercurial doesn't support this. The correct way to do it is to commit thefile.sample and then have your developers (or better you deploy script) do a copy from thefile.sample to thefile if thefile doesn't exist. That way anyone can update the example file, but there's no risk of them committing their local changes (say their personal database connect string).
Aha! So TortoiseHG's repository and global settings have an Auto Exclude List where you can define a list of files that will be unchecked by default when the status, commit, and shelve dialogs open. So they still show up, but the user has to check them in order to actually do a commit. The setting is stored in hgrc, but it's under the [tortoisehg] heading so it's not supported by mercurial per se. Nevertheless, it fits my needs.
One solution to this is to use nested tree support (submodule in git), where the "junk" would be put in a different repository (to avoid cluttering the main repo), while enabling checking out the whole thing out in a consistent manner (right version of both repos in sync).
https://www.mercurial-scm.org/wiki/Subrepository?action=show&redirect=subrepos
In git, submodules are one solution to this issue - but they are not that great UI-wise. What I do instead is to keep two completely independent repositories, and using the subtree merge strategy when I need to update the main repo with the junk repo: http://progit.org/book/ch6-7.html

Mercurial (Hg) and Binary Files

I am writing a set of django apps and would like to use Hg for version control. I would like each app to be independent of the others so in each app there may be a directory for static media that contains images that I would not want under version control. In other words, the binary files would not all be in one central location
I would like to find a way to clone the repository that would include copies of the image files. It also would be great if when I did a merge, if there were an image file in one repo and not another, that there would be some sort of warning.
Currently I use a python script to find images and other binary files that are in one repo, but not the other. But a lot of people must face this problem, so there must be a more robust and elegant solution.
One one other thing...for reasons I do not want to go into, usually one of my repos is on a windows machine, and the other is on Linux. So a crossplatform solution would be nice.
Since Mercurial 2.0 the extension largefiles is now included in the main distribution. That extension keeps and manages large files outside of the "normal" repository in a way that you get the benefit of DCVS but without the benefit of exponential size and processing time growth.
Other extension that work along similar lines are SnapExtension and BigFilesExtension. However, those two are not distributed with Mercurial (you have to get them manually).
Mercurial can track any kind of file, for binary files if something changes then the whole file gets replaced not just the changes.
On the getting a warning if one repo doesn't contain a file, that's kind of the point of a DVCS is that the repos are related but are autonomous. You could always check and see what files were added during a synch or merge operation.
The current Mercurial book (by Bryan O'Sullivan) says, that Mercurial stores diffs also for binary files. How efficient this is, obviously depends on the nature of changes to binary files.