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.
Related
I want to search for a filename across all my commits/branches and find out which commits/branches contain that filename. I don't know which subdirectory/subdirectories of the repo the file would be in.
I've tried hg grep <filename>, but that only seems to show files containing "filename".
I've also looked at Mercurial - determine where file was removed?, but that really help me if a file was created on a different branch. The person asking that question suggested hg log myfile -v, which seems like it could work, but doesn't. I know that somewhere in my repo the file exists because I get something back when I do find .hg | grep <filename>, but that doesn't tell me (at least not clearly) which commits/branches.
You have to read hg help patterns and maybe hg help filesets in order to write correct pattern for the file (most probably you'll be happy with just pattern)
If file exist now in working directory (i.e. was added and not removed later), you'll find it with hg file <PATTERN> and will determine full path by output, see above (pattern used)
>hg file **/test-extra.t
tests\test-extra.t
and call hg log with full filename
In any case (hg file returned 0 for removed file or file still in WD) you can call hg log <FILESET> and get history too. Log for existing will be too long, will show deleted unique filename sample
>hg log set:**/dulwich/tests/__init__.py -Tcompact
223 0b6c08800d16 2009-07-23 08:48 +0100 a
delete the dulwich fork we have
2 c43c02cc803a 2009-04-22 16:59 -0700 schacon
added dulwich library and got the script to call it for clone
If your set will be too wide and (may) include files with the same name in different folders, you have to verify filenames by calling log with more details about files, f.e. with -Tstatus
hg log 'glob:**/<filename>` -Tstatus
seems to do the job. It doesn't give me the commits containing <filename>, but it does give commits (and their branches) involving filename.
Credit to Lazy Badger's answer for pointing me to this.
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
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()
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.
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.