Can I use wildcards in the filemap of hg convert - mercurial

I have a repository with one file (subdir/a.txt), and the one revision, adding it.
If I run hg convert with a filemap consisting of include subdir/a.txt, it works just fine.
But if the filemap is include subdir/*.txt, include */a.txt, or include **/*.txt, the resultant repository has no revisions in it.
Is it possible do use wildcards in the filemap of hg convert?
--
The reason I want to do this is so that I can create a new repository with history, but without any binary files. I want to be able to do something like exclude **/*.dll. Is there any way to do that?

Wildcards do not seem to be supported, but you can use hg manifest --all to get a list of all files present in all changesets, and do some filtering and editing of the output to generate what to exclude. Something like the following to list all the DLL file paths on Windows:
hg manifest --all | findstr \.dll

Related

How can I grep a specific file in a specific revision (unchanged in that revision) in Mercurial

I have several repositories that I am building a tool to interact with. I have not been able to find a way to grep a specific file in a specific revision that was unchanged in that revision.
The help for hg grep says that the -r option -r --rev REV [+] only search files changed within revision range. If I update the revision in question, I can grep appropriately, and I get the desired results. Because my file in question is unchanged in that revision, it will not get grepped. Does anyone know a way to do this?
My end goal is that I would like to ignore files that meet a certain pattern matching. I am not sure that using the --all option would be feasible, because I would have to parse the revisions that the pattern appeared and disappeared in.
Thanks in advance.
edit:
Actual problem I'm trying to solve:
There are several tagged revisions in a repository.
For each of those tagged revisions, I would like to extract a particular file (assume source/a.c or something like that) to a folder structure that others can access (a website for those outside of our group, whom we cannot give repository access to).
But, I would only like to extract the file if it does not contain a particular pattern. This is why I would like to check the file at a specific revision, even if it has been unchanged.
Right, hg grep indeed does not analyse the file contents at a particular revision but only when the file actually changes. Thus I suggest a slightly different way:
Get the revisions to check as a nice list:
hg log -r"tag()" --template="{rev}\n"
Using it this way (instead of tags) allows to also look at revisions which are not tagged. If it's really only tags, you might resort to the hg tags command directly: `hg tags --template="{tag}\n". It would make the $i in the small script below a nice tag name instead of a revision :)
You can use this list to get the file FILENAME at those respective revisions and then you need some small script which actually checks that file for the content in question:
for i in $(hg log -r"tag()" --template="{rev}\n"); do
if hg cat FILENAME -r$i 2>/dev/null | grep PATTERN > /dev/null; then
hg cat FILENAME -r$i > path/to/whereever/FILENAME.$i
fi
done

Splitting subfolders of an SVN repo into individual Mercurial repos results in error "abort: expected trunk to be at 'trunk/module1', but not found"

I have an SVN repo with structure like this:
/branch
/tags
/trunk
/trunk/module1
/trunk/module2
/trunk/module3
I am trying to separate this into individual Mercurial repos, where each new Mercurial repo retains the revision history of that module's files. The end result would be
/module1-hg
/module2-hg
/module3-hg
Based on this guide (http://wiki.colar.net/selectively_converting_subversion_repository_to_mercurial),
I have tried using
hg --config convert.svn.trunk=trunk/module1 convert https://repo.url/ module1-hg
but that results in the following error:
abort: expected trunk to be at 'trunk/module1', but not found
I am able to convert the whole SVN repository, but I'd really like to separate the modules at this point. I feel like I just can't find a good example of the syntax to split these apart. Can anyone help?
I recently did this but I did it in several steps.
Firstly, I converted the whole repo to be a mirror of the SVN repo. I used the hgsubversion extension for this but if you've done it using the convert extension then that's fine.
The second step was where I split the repos up. I used the convert extension with a filemap to exclude some folders and rename others.
For example:
hg convert bigrepo module1-hg --filemap module1.txt
And module1.txt would contain the following:
exclude module2
exclude module3
rename module1 .
That would create a repo called module1-hg excluding modules 2 and 3. It would also move the source of module1 into the root of the repo instead of a subdirectory.
You could then repeat the action for modules 2 and 3 with similar filemap files.

How do I make mercurial ignore any file with .xxx extension

I want Mercurial to ignore any file with a certain extension.
For example, I wanted to ignore files with a .SUO extension. (There's no need to version-control Visual Studio user settings.)
So I changed my .hgignore file to this:
syntax: glob
*.suo
However, this has no effect, and Mercurial still sees my .suo file.
What am I doing wrong here?
If, when running hg status before altering your .hgignore file, the .suo file had a ? in front of it, then it should be ignored now. If anything else (M or A for example) it is already tracked by the repository and will not magically stop being tracked. In such a case you'll need to do hg remove on the file to delete it and have hg stop tracking it, or just do hg forget on it to have hg stop tracking it but keep the file. Either should be followed by a commit.
The only files that will be omitted from the status listing if their path matches a pattern in the .hgignore file are files that are not tracked. It would make no sense to omit a file that is tracked, because you would never see whether it had been modified, added, or removed.
Edit: Mercurial does only track files (you can't make it track empty directories), but the patterns in .hgignore are simply run against strings of the file paths relative to the root of the repository. The very same relative paths that it shows you when you run hg status. So it does work how you say you want it to work because the following lines are a standard part of my own .hgignore files:
syntax: glob
*\obj\*
*\bin\*
*.csproj.user
*.suo
Again, when you run hg status and it shows a .suo file, what single character is at the beginning of that line? Is it a M, A, R, ! or ? character? What is the path after it?
Mercurial uses entries in a file called .hgignore to determine what files it completely ignores. It is normally located in the root file for your repository (and not in the .hg directory, which you might think).
You can find out more here:
http://www.selenic.com/mercurial/hgignore.5.html
Normally, we use regular expression syntax to ensure that case is not a factor in extensions:
# use regexp syntax.
syntax: regexp
(?i)\.dcu
(?i)\.identcache
(?i)\.dof
(?i)\.dsk
(?i)\.bak
(?i)\.old
That way, it ensures that even if for some reason the case of the extension changes, it is still ignored.
Example for ignoring/excluding files with .o extension:
.*\.o$
should translate to .*\.suo$ for .suo extensions.
I have used this method successfully
Check where .hgignore file is located and ensure it is either in $HOME or project root folder. Check the CASE (vs case) of the extension. I doubt if pattern matching is case insensitive.
edit: tested, the pattern matching is NOT case sensitive. Hence, add "*.SUO" if you want to ignore files with ".SUO" extension.

delete files in history to save some space in mercurial

ok, when I was young, I put severial big files(like resource file, dll, etc..) in my mercurial repos. and I found the size of it is so big that I cannot easily push it into bitbucket,
any way to delete this files history EASILY?
I put all those files in /res and /dll path.
edit:
this is a solution, but it will delete part of the history, so maybe there is a better solution.
Mercurial Remove History
Your best bet is to use the convert extension, but warning you'll end up with a totally different repo. Every hash will be different and every person who cloned will need to delete their clone and re-clone.
That said, here's what you do:
Create a filemap file named filemap.txt containing:
exclude res
exclude dll
and then run this command:
hg convert --filemap filemap.txt your-source-repository your-destination-repository
For example:
hg convert --filemap filemap.txt /home/you/repos/bloatedrepo /home/you/repos/slenderrepo
That gets you a whole new repo that has all of your history except the history of any files in /res and /dll, but again it will be a new, unrelated repo as far as mercurial (and bitbucket) are concerned.

funny that when .hgignore is added for Mercurial, this file itself shows up as "?" in hg status?

Is it normal? So you just need to add \.hgignore to the list to ignore itself?
Yes, but you don't want to ignore the .hgignore file. When a new person checks out your repository, don't you want them to get your ignored-files list? Instead, do hg add .hgignore; hg commit.
Bottom line: .hgignore is tracked like any other file in the repository.
Just to supplement Borealid's answer: ? in hg status means that the file is in the working directory, but not tracked. You usually see it in one of two situations:
A file got generated that you don't need to check in, like a compiled binary or something.
You added a new file to your project, but haven't hg added it yet.
In #1, you'll want to add the file or file type to .hgignore. In #2, you want to hg add the file. In the case of .hgignore, it's #2.