Can I set Mercurial config options programmatically? - mercurial

I'm looking for a way to set .hgrc configuration items without actually editing the text file. I'm trying to standardize the setup of the hgrc across multiple developers and I would like a command like
hg --config ui.username=foo
but which also saves that config change into the hgrc file.
It seems like this should be something that should be supported directly in the vanilla hg command, but I can't find it anywhere.

Someone -- either you or Mercurial -- will have to edit the configuration file if you want the config change to be saved :-)
And if you can call Mercurial with
hg --config ui.username=foo
then you should also be able to do
echo '[ui]' >> ~/.hgrc
echo 'username = foo' >> ~/.hgrc
which will save the config change, not matter how the ~/.hgrc file happens to look like (it is okay to have multiple [ui] sections).
Mercurial 3.0 and later has the hg config --edit command that opens an editor with the user config file. Still not quite what you're asking for, but at least this makes it easier to edit the file interactively.

This form:
hg --config ui.username=foo
Doesn't save anything. It sets the value for just the one run.
Also you can use /etc/mercurial/hgrc for system wide settings if that helps anything.

There is an extension that helps with this, https://bitbucket.org/alu/hgconfig/wiki/Home
After installing that hgext, you can do things like this.
% hg showconfig paths
paths.default=ssh://hg#bitbucket.org/alu/hgconfig
% hg config paths.upstream $(hg showconfig paths.default)
% hg config paths.default $(hg showconfig paths.default | sed 's|/alu/|/nassrat/|')
% hg showconfig paths
paths.default=ssh://hg#bitbucket.org/nassrat/hgconfig
paths.upstream=ssh://hg#bitbucket.org/alu/hgconfig
The only gotcha is this overrides the builtin config command, you can either tweak the code to change the command name, or live with it. Fortunately, it probably would not matter if your use case is simply to set and get specific configs.

Related

Why don't mercurial file sets work when adding files?

I'm trying to use mercurial file sets to add all the files in a directory tree, excluding very large files and any binary files. Cribbing from the mercurial documentation, this command should do it:
hg init
hg add 'set: size("<1M") and not binary()'
However this returns a status code of 0, and hasn't added anything to my new, empty repo. I've tried just 'set: not binary()' and that didn't work either.
The frustrating thing is that although I can google for mercurial file sets, and find lots of examples, I can't find anything to help troubleshoot when it doesn't work!
I don't have a .hgignore file, and it's a fresh empty repo. Mercurial 4.2.2.
The directory where I'm testing this has a couple of artificially created files for the purpose of testing. In my real use case, I inherit a multi-gigbyte tarball of assorted sources and binaries from a client, and I want to get all the sources into mercurial before I start hacking to fix their problems, hence the need to exclude the binaries and large files that otherwise choke mercurial.
Here's my little test script:
#!/bin/sh -ex
dd if=/dev/urandom of=binary_1k bs=1 count=1024
dd if=/dev/urandom of=binary_2M bs=1 count=2097152
echo "This. Is, a SMALL text file." > text_small
hexdump binary_1k > text_1k
hexdump binary_2M > text_2M
ls -lh
file binary_1k
file binary_2M
file text_1k
file text_2M
hg init
hg add 'set: size("<1M") and not binary()'
hg status -a
hg add 'set: not binary()'
hg status -a
hg add 'set: size("<1M")'
hg status -a
At the end of this, each status command reports no files in the repo, and the add commands report no errors.
The problem is that file sets do a query of Mercurial's repository data base, which knows only about files that are part of the repository or have been added.
One solution is to add all, and then to get rid of the files that you don't like, e.g.:
hg forget 'set:size(">1M") or binary()'
This works, because the query also requires recently added files, even if they haven't been committed yet.

Mercurial - Always take local for files matching on a specific folder

I need to set up Mercurial HG in order to always take local version of a file that matches in a specific folder.
EG: when conflict on /**/dist/ always take local
This because I need to commit some built files.
Thanks in advance
EDIT:
I need to commit some files generated by some processors (libsass, webpack), it depends on a temporary unavailability of my build-system. So, I removed these files from the hgignore. Now, the problem that I'm having is on Mercurial conflicts on these generated files. I want automate the merge-resolving using the local version of these files. similar to: How to keep the local file or the remote file during merge using Git and the command line? but for Mercurial HG
You can put a merge-pattern in your ~/.hgrc or .hg/hgrc to specify the default tool for a merge for a given file:
[merge-patterns]
**/dist/* = :local
The :local merge tool will prioritize the local version. See hg help merge-tools for a full list of internal merge tools. Note that using the --tool option during a merge will override this choice; however, setting the ui.merge option to define your default merge tool will not.
The **/dist/* pattern may or may not be what you need. Please adjust it to your needs (and note that regular expression patterns are also available for additional flexibility if required).
Alternatively, you can also automatically resolve these files after the merge, e.g. with:
hg resolve --tool :local $(hg files -I '**/dist/*')
Or, if the list of files is too large to fit on the command line:
hg files -0 -I '**/dist/*' | xargs -0 hg resolve --tool :local

TortoiseHG forget files in all sub folders of specific name

I have a pretty large folder (with many sub folders) on a mercurial repository. I was a bit too fast with my first commit so I added a lot of files that i now realize shouldn't be on version control. I've updated my .hgignore file accordingly but all the old files are still version controlled. Is there a command that I can write in the root directory that forgets all files that are in a folder of a specific name. These folder names exist in a lot of places and i want them all forgotten with one command since it would take a long time to go through them all manually and forget the folders/files
I guess it would maybe look something like this:
hg ignore ../folderName/
Yes... use a pattern to match them like
hg forget FOLDERNAME**
hg commit -m "Forget FOLDERNAME"
hg help forget
hg forget [OPTION]... FILE...
(...)
options ([+] can be repeated):
-I --include PATTERN [+] include names matching the given patterns
or use a one-line script:
for i in $(hg ma | grep FOLDERNAME); do hg forget $i; done
You can read hg help filesets and use one of it's samples
Forget files that are in .hgignore but are already tracked:
hg forget "set:hgignore() and not ignored()"

How to tell Mercurial not to look for root from ignored sub-directory

So here's the problem. I have my configuration file in my home directory ~ under Mercurial control. Part of the
|-~
|.hg/...
|-Dev
|-Project1/...
|-Project2/...
.hgrc
.hgignore
I have Dev directory excluded from the source control in .hgignore file.
However when I am in the directory ~/Dev/Project1 Mercurial thinks that I am in the under the source control. If I type hg root in any directory that is in the .hgignore or its sub-directory hg still considers it being a part of repository.
Is it a bug or a feature ?
UPDATE
So, here's the simple experiment one could do from the command line:
% mkdir -p /var/HgTest
% cd /var/HgTest
% hg init
% echo "this is a repository file" >> test.txt
% hg commit -Am "added repo file"
% cat <<EOT >> .hgignore
heredoc> syntax:re
heredoc>
heredoc> ^Dev
heredoc> EOT
% hg commit -Am "added .hgignore"
% echo "This is not in repository" >> Dev/notinrepo.txt
Now, Dev directory not in repository, if you type hg st anywhere under /var/HgTest it shows you that repo is clean. However if you go into Dev directory and type hg root it will output /var/HgTest. This is perhaps desired result. However, since the path should be ignored, I would think that hg root should effectively exit with -1 return code and message "not in repository" or something like that.
In my case, having HOME directory under source control effectively makes some of the tools consider every new directory (even under ignored paths) as a part of Mercurial repository located in the HOME directory.
It's a feature for when you are in ~/Dev/Project1/deeply/nested and want to keep mercurial commands within the scope of Project1.
A workaround is to hg init in ~/Dev/Project1. Part of the problem is the bad practice of putting your home directory under version control; I can see no benefit to be gained from it and much cost. As an example, almost everything you do with a browser, or music player, or many other programs is going to alter files in ~/.groovy-game/config or ~/.browser/cache-files; there is no meaningful way to choose a commit point. Because of this it would be better to establish good, incremental snapshot backups for $HOME, even if they are stored on the same machine.
This is not to say that dot-directories in your home should never be versioned. for example, suppose I hack on my ~/.vim files because I am working on the ultimate editing environment, cd ~/.vim; hg init can certainly be useful.
Put another way — so long as there is an .hg repository somewhere in the tree above you, Mercurial will seek it out and read the ignore file and not take action on ignored paths. However, hg root only looks for an .hg directory. In your case, there is always a root, you are in your ~ repository by definition. I don't see how it could be done otherwise; you can't find the ignore file until you've inspected the root.

Mercurial: make `hg log` not show files?

I'm (ab)using Mercurial to manage thousands of files that change often, but I'd like to be able to view the log (hg log) without having my term filled with all of the filenames that changed on each commit. hg log -q is a little too quiet, since I need to see the descriptions. Is there a flag I'm missing for hg log?
It sounds as if you might have the verbose flag turned on. You can check by running hg showconfig and looking for a line like ui.verbose=true.
There are a few ways you can fix it:
remove that line from the offending configuration file (Mercurial can use several, and they vary by OS: use hg help config to list the possibilities).
override the flag in your repository's .hg\hgrc or your private Mercurial configuration (Mercurial.ini or ~/.hgrc): add the following lines to it:
[ui]
verbose=false
clear the verbose flag on the commandline: hg log --config ui.verbose=false.