How can I store persistent data with a mercurial extension? - mercurial

I'm writing a mercurial extension and I need to store a small amount of metadata. This is a dumb example, but enough to get something like this to work:
$ hg myextension --set a=2
$ hg myextension --get a
2
This data does not need to be copied if the repo is cloned, although if that's easy it would be cool to do that.
What is the proper way to do this in a mercurial extension? Is there a folder under .hg that I can just create arbitrary files in or something like that?

There is no built-in mechanism for this — each extension decides how to best store the data. Extensions usually store their data in a file or directory named after themselves, so you could use
.hg/myextension/
as your root. You can use repo.opener to open files inside that directory:
fp = repo.opener('myextension/state.json')
data = json.load(fp)
fp.close()

Related

Mercurial batch rename to change file types

Dumb thing, we are changing our code standard that all C++ header files need to be ".hpp" instead of ".h" (leaving .h to be C compatible headers). So my library only has *.h files in it. Is there a quick way built in to mercurial to do this rename or do I need to write my own script?
Mercurial has a way to do it if you want to rename them in all revisions back to the start of time (and thus change history and invalidate any clones), but since you probably don't want do do that you can just do:
for thefile in $(find $(hg root) -name '*.h') ; do hg rename $thefile ${thefile}pp ; done

hg pull/update only if local repository is "clean"

I want to write a script that recursively descends a directory tree, and does an hg pull -u on all repositories that are "clean" - i.e. have no local diffs, outgoing changesets, or anything else that might make them different to remote. (The script would also do a rebuild, etc.)
Is there a good way to check whether a repository is "clean"? Keep in mind that I would probably be doing this from a bash or python script.
hg status is your friend. However, you should be careful about what "clean" means. If all files in your directory structure are under version control, and none of them have changed, hg status should return no console output, and (probably) a 0 return code.
If that does not match your definition of clean, you have to be more careful. For example, I commonly do not add generated files (binaries, PDFs from Latex, etc) to version control, but they are inside my directory structure. In that case these files are listed as 'unknown', and I'm sure the return code of hg will differ.

tool to inspect mercurial's internal files

Git has the cat-file command to inspect internal files, e.g. git cat-file blob 557db03 will show the contents of the object whose hash starts with 557db03.
Are there similar tools for mercurial that allow me to look at all the different data files that merfcurial uses internally?
Try hg --debug help and you can see the list of all the debug commands:
debugancestor:
find the ancestor revision of two revisions in a given index
debugbuilddag:
builds a repo with a given DAG from scratch in the current empty repo
debugbundle:
lists the contents of a bundle
debugcheckstate:
validate the correctness of the current dirstate
debugcommands:
list all available commands and options
debugcomplete:
returns the completion list associated with the given command
debugdag:
format the changelog or an index DAG as a concise textual description
debugdata:
dump the contents of a data file revision
debugdate:
parse and display a date
debugdiscovery:
runs the changeset discovery protocol in isolation
debugfileset:
parse and apply a fileset specification
debugfsinfo:
show information detected about current filesystem
debuggetbundle:
retrieves a bundle from a repo
debugignore:
display the combined ignore pattern
debugindex:
dump the contents of an index file
debugindexdot:
dump an index DAG as a graphviz dot file
debuginstall:
test Mercurial installation
debugknown:
test whether node ids are known to a repo
debugpushkey:
access the pushkey key/value protocol
debugrebuildstate:
rebuild the dirstate as it would look like for the given revision
debugrename:
dump rename information
debugrevlog:
show data and statistics about a revlog
debugrevspec:
parse and apply a revision specification
debugsetparents:
manually set the parents of the current working directory
debugstate:
show the contents of the current dirstate
debugsub:
(no help text available)
debugwalk:
show how files match on given patterns
debugwireargs:
(no help text available)
There are a lot of them, and they pretty much expose everything.
The closest commands would be:
hg cat -r rev aFile
hg cat: Print the specified files as they were at the given revision
This is not completely the same than git cat-file though, as the latter can also list SHA1, type, and size for a list of objects.
In that second case, hg manifest might be more appropriate.

Create a new repo from sub folder in Mercurial Repo using convert

I am trying to extract a folder (call it Project1) from an existing Mercurial Repo (call in MainRepo) using the Convert extension for Mercurial to Mercurial conversion. I have followed the methods described by Mercurial developers (and elsewhere on the web) under Windows XP:
C:\MainRepo>echo include Project1 > ~myfilemap
C:\MainRepo>echo rename Project1 . >> ~myfilemap
C:\MainRepo>hg convert --filemap ~myfilemap . C:\Project1Repo
C:\MainRepo>cd \Project1Repo
C:\Project1Repo>hg update
This creates the new repo (Project1Repo) with the Mercurial folder/files in place.
But it does not:
1) Carry across the History relating to the changes made for the Project in folder Project1. (Only the very first history entry for MainRepo and a Convert item are present).
2) Copy across all the source code files from the MainRepo\Project1 to Project1Repo.
I have seen the other similar questions and answers in stackoverflow but these do not appear to help (I have followed methods discussed in them):
Can I clone part of a Mercurial repository?
So the question is: How do I extract a sub-folder from MainRepo with only the sub folder history intact and complete to a new Repo and transfer the source files at the same time? (though I guess a straight copy will do the last). It's keeping the history that is important - In this case I can make this after a date or Changeset number.
Any help much appreciated as I'm relatively new to this
Thanks
The workflow you listed is correct. That is the way the convert extension is intended to work.
Your question states that the repo output by hg convert is actually empty (except for "the very first history entry for MainRepo and a Convert item"). This would indicate that convert was not able to find the path specified in your filemap.
Are you certain that the path given your include statement is correct?
The directory name given in your include statement must be the full path from your repository root. For example, your include statement:
include Project1
requires that the path to Project1 actually be:
C:\MainRepo\Project1
If Project1 is actually located somewhere else in MainRepo, you will end up with an empty repo after the conversion.

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.