About TortoiseHg
TortoiseHg is a Windows shell extension and a series of applications for the Mercurial distributed revision control system.
Introduction
This tip presents a repository tool named TortoiseHgManager
created for TortoiseHg
to verify all repositories in one click. I assumed that you have a basic knowledge of TortoiseHg
and Mercurial
.
Background
Contents of a Mercurial
repository are stored as a sub folder named ".hg". This folder contains multiple files which hold the status and history for each tracked file. The integrity of this folder is important for the repository to work properly. There is a chance that files in the repository folder will get corrupted due to either a hardware or software error. One may still be able to commit to a damaged repository but getting an earlier revision may no longer work.
Repository Verification
Mercurial
and TortoiseHg
do provide a verification function to verify the integrity of a repository. The verification function can be accessed from the TortoiseHg
Workbench under Repository --> Verify.
This function works fine for one repository at a time. However, it is very tedious to verify all repositories as there isn't any function to do this in one click.
About TortoiseHgManager
TortoiseHgManager
is created to automate the repository verification for all Mercurial
repositories registered under the TortoiseHg
Repository Registry. This tool will perform repository verification on all repositories and report its status. The number of repositories which failed verification are shown in the status bar as below:
Load Repositories from Repository Registry
The TortoiseHg
repository registry is stored in the following location: "%APPDATA%\TortoiseHg\thg-reporegistry.xml". TortoiseHgManager
retrieves the repositories information from this file.
Verify Repositories
The Mercurial
verification function is used to verify each repository as shown in the TortoiseHg
Workbench. The command is given as below:
Command: hg --repository <Repository Path> verify --verbose
The Mercurial
command is executed using the Process
class.
Process p = new Process();
p.StartInfo.FileName = "\"C:\\Program Files\\TortoiseHg\\hg.exe\"";
p.StartInfo.Arguments = "--repository \"" +
repositoryPath + "\" verify --verbose"; ;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.WorkingDirectory = Path.GetDirectoryName(repositoryPath);
p.StartInfo.CreateNoWindow = true;
p.Start();
Multithreading Support
To avoid freezing the main window, we employed a background worker to manage the verification process for each repository. To speed things up, we use the Parallel.For
in the background worker to run multiple verification processes. Each iteration of Parallel.For
will spawn one thread.
Parallel.For(0, dgRepo.Rows.Count, taskOption, rowIndex =>
{
if (UserAborted) return;
DataGridViewRow ptrRow = dgRepo.Rows[rowIndex];
if (VerifyRepository(Repositories[ptrRow.Index], ref errorMessage))
UpdateStatus(ptrRow, "OK", true);
else
UpdateStatus(ptrRow, "ERROR", false);
});
Verifying N repositories with N threads doesn't sound practical. It will run even slower when there are too many threads running at once. To optimize the performance, we limit the threads in the Parallel.For
by setting the MaxDegreeofParallelism
property in ParallelOption
. This option is settable from the track bar located on the upper left of the Application's Main Form with max thread limited to 8.
New Features
Push and Pull Changes (Version 2.0 onwards)
Added new function to push or pull changes from multiple repositories with alias named "default
".
This is handy to sync between multiple repositories on local machine and remote server or external storage.
Fix Repositories (Version 2.1.0 onwards)
Added new function to repair damaged repositories with status "ERROR
" during repositories verification.
If the repositories is damaged for whatever reason, this feature can help to recreate the changeset without losing the histories from previous changeset.
However, the cost of repairing a damaged repositories is a new ID that will be assigned to a new change set.
History
- Version 2.1.0
- Fixed infinite loop when 'Fix Repositories' failed
- Fixed "Fix Repositories" not triggered
- Version 2.0.0
- NEW: Fix damaged repositories (Warning: This feature will create a new change set ID)
- NEW: Pull changes from default repository
- NEW: Push changes to default repository
- NEW: Added repository filter
- Version 1.0.0 - Initial release