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

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

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.

Would like to do a mercurial clone with filter of patterns in hgignore

Over time a number of the developers have committed files that were then added to the .hgignore. From what I hear there is no way to remove items from the history of mercurial, which is ok. But I also heard that there is a way to do a clone, I think using the convert plugin, to clone/export a repo while specifying which files to not include in the conversion.
I can't help but think that someone out there has a script that does this export/filter/convert using the patterns from the .hgignore file.
Has anyone created such a beast?
You could create a filemap from .hgignore doing something like this:
hg clone -U yourrepo temprepo # create a temp repo with no files in working dir
cd tmprepo
hg revert --all # put files in working dir
hg forget ** # un-add the files
hg status --ignored --no-status | sed 's/^/exclude /' > ../filemap
that will get you a filemap you can pass into hg convert that removes all the added files that would be ignored given your .hgignore.
Do understand though, that running convert creates a whole new repo that is unrelated to your previous repo. All existing clones will be unusable with the new one. It's not normally worth it.
hg convert is indeed the thing you want to use.
You will want to create a file map (just a text file) which will list all of the things you either want to include, exclude, or rename:
include subfolder
exclude subfolder/supersub
etc...
Read the following for a more concrete example:
https://www.mercurial-scm.org/wiki/ConvertExtension#A--filemap
Once you have created this file you will just use the following command:
$ hg convert --filemap my_file_map /path/to/source/repo /path/to/dest/repo
The source repo will not be modified and a dest repo will be created. I don't want to just copy verbatim what the documentation already says so here is the link:
How to keep just a subdirectory (or run on the mercurial repo):
https://www.mercurial-scm.org/wiki/ConvertExtension#Converting_from_Mercurial

tortoisemerge with Hg reports all lines as changed

I'd like to use TortoiseMerge with Mercurial to resolve conflicts, but its reporting every line in theirs and mine as added as though its not comparing properly
here is my mercurial.ini:
[ui]
merge = TortoiseMerge
[merge-tools]
TortoiseMerge.executable=C:\Program Files\TortoiseSVN\bin\TortoiseMerge.exe
TortoiseMerge.args=/mine:$local /theirs:$other /base:$base -o /merged:$output
I'm using Hg 1.7.5
What's going on?
Update: When using KDiff or BeyondCompare, the base is always empty.
Thanks
Your setup appears correct.
This is symptomatic of having no copy of the file in the base revision, in which case Mercurial acts as if the file was present but empty.
There are a couple ways of figuring out what's going on here. If there are no copies or renames involved, you should be able to simply do:
$ hg log -r "ancestor(p1(), p2())"
..to determine the ancestor of the merge, then:
$ hg manifest -r <rev> | grep <your file>
..to determine if the file was in fact present.
Alternately, you can run 'hg merge --debug' or 'hg update --debug' to see what changeset and file it's choosing for the merge (including rename/copy details).
If you find that the file is present in the common ancestor Mercurial chooses, then you should report a bug (including your debug output) at:
https://www.mercurial-scm.org/wiki/BugTracker

Can I set Mercurial config options programmatically?

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.

Is there an ignore-on-commit option in mercurial?

Is there any way to ignore changes to some files on a commit with mercurial?
I've got a specific situation where we have a default oracle tnsnames.ora file that points to 127.0.0.1, but some developers will modify it to point to other systems, but we don't want to change the default file.
In subversion, I've simple added this to the ignore-on-commit changelist. Is there a way of doing this in mercurial?
If the files you want to omit from the "hg commit" command are already "tracked", you should use the -X option. The pattern passed to -X is pretty flexible, making it possible to run for example:
% hg stat
A etc/foo.conf
M src/bar.c
M lib/libbar/loader.c
% hg commit -X '**.conf'
to avoid committing any file with a ".conf" extension, regardless of how deep in the source tree it lives. In the workspace shown above this would commit "src/bar.c" and "lib/libbar/loader.c" but not "etc/foo.conf".
To exclude multiple patterns of filenames, use multiple -X options, i.e.:
% hg commit -X '**.conf' -X '**.sh'
Traditionally, this is solved by not versioning the file itself, but by versioning a copy of it as a template for others to use.
So you would hg mv tnsnames.ora tnsnames.ora-template, then commit, then do a straight filesystem copy of tnsnames.ora-template to tnsnames.ora, and add tnsnames.ora to the .hgignore file.
Subsequent changes to the template will still get pushed out, but they won't actually change the working environment unless someone copies the template to the actual file.
You could alias commit to something like 'hg commit -X excluded_file.ext' I've never used mercurial, so I'm just going by the man page here.
Look for .hgignore file in Mercurial's documentation.
Here is an example ignore file.
# use glob syntax.
syntax: glob
*.elc
*.pyc
*~
# switch to regexp syntax.
syntax: regexp
^\.pc/