Compare Mercurial Repos
I have a bunch of Mercurial repositories on my Windows workstation. We're a small shop, and on some days (usually bad ones) I may make changes / bug fixes in half a dozen or more of my projects. Some of these projects are in maintenance mode, they're only touched once a month or so. Of course, I sometimes get interrupted before I get to push to our central Hg server.
Is there an easy way to regularly compare a bunch of my repos with the central server? It should warn me if I have changes that haven't been pushed. Ideally, something that sits in the system tray and alerts along the lines of "Local change older than 48 hours not in remote repo."
I suppose I should just set up a script to go through my repos and compare them. I could get in the habit of running the script daily.
开发者_如何学CThoughts?
I use helper functions in my Powershell profile. They're easy enough in other scripting languages, though I wouldn't dare to do it in .bat or .cmd files.
I keep a file D:\repos.config
with a list of the absolute paths of all the local repositories I want to quickly glance at for 3 things: status summary, incoming changes, outgoing changes. Examples that follow assume a file with these contents:
D:\repository1
D:\repository2
#D:\ignoredrepo
D:\repository3
D:\repository4
For checking the status, the script does $results = hg -R $path st
to get the status list and then I count first-characters only, printing 1 line for the repo path and 1 line for status summary for each repository path (if there's anything to show):
----- D:\repository1
M 1 - A 1
----- D:\repository4
? 3
For incoming/outgoing, I keep my [paths]
in each repository's hgrc
concistent so that the default
is always the repository on our server, bb
is the one on bitbucket, etc. I loop through the same list of paths, executing $results = hg -R $path $type $alias --template '{rev} {node|short} {desc|firstline}\n' for each.
$typeis either
inor
outdepending on which I've called and
$aliasis the path alias that should be in each repo's
hgrc(empty string for
default,
bb,
backup, etc.). I do a little processing of
$results, since the first 2 lines are not actual changesets. You'd probably want
{date|age}or
{date|shortdate}` in your template if you wanted to filter out anything less than 24 hours old.
This way I can write simply hgouts bb
at the prompt and see concise output. Some repositories don't have a particular alias at all, so 2>$null
helps prevent some abort: repository bb not found!
messages.
----- D:\repository2
150 f7364a6f78d2 integrate FooBar
151 7a3d3d9fb0d0 fixes #1214; thingamajig wasn't getting closed
----- D:\repository4
4 dd88f00d93ff more changes to the doojiflopper
As for synchronizing multiple repositories, I'm satisfied enough with TortoiseHg 2.0 and its Repository Registry to help me do them 1 at a time after I use the script to tell me which ones I need to do. But it also wouldn't be terribly complicated to loop through the paths and hg -R $path pull -u
or hg -R $path push
en masse, or use bits of the script to selectively pull/push only what's needed that doesn't have changes in the working directory. It's just not something I've needed yet.
Edit: I took a bit of time to clean up the code just a little. The functions hghg
is the status summary, and the functions hgins
[alias]
and hgouts
[alias]
are what I actually call from the prompt.
function hghg(){
$repos = [io.file]::readalllines('D:\repos.config')
$repos | % {
if (!$_.startswith('#') -and (test-path $_)){
hg-st $_
}
}
}
function hg-st($path){
$x = hg -R $path st
if ($x.length -gt 0){
write-host "----- $_"
$d = @{}
$x | % {
$c = $_[0]
if (!$d.containskey($c)){
$d[$c] = 0
}
$d[$c] += 1
}
$p = @()
$d.keys | % {
$cnt = $d[$_]
$p += "$_ $cnt"
}
write-host ' ' ([string]::join(' - ', $p))
}
}
function hgins($pathalias){
hg-inouts 'in' $pathalias
}
function hgouts($pathalias){
hg-inouts 'out' $pathalias
}
function hg-inouts($type, $pathalias){
$repos = [io.file]::readalllines('D:\repos.config')
$repos | % {
if (!$_.startswith('#') -and (test-path $_)){
hg-inout $type $_ $pathalias
}
}
}
function hg-inout($type, $source, $target){
$x = hg -R $source $type $target --template '{rev} {node|short} {desc|firstline}\n' 2>$null
if ($x.count -gt 2 -and $x[2] -ne 'no changes found'){
write-host "----- $source"
$y = $x[2..($x.length - 1)]
$y | % {write-host ' ' $_}
}
}
精彩评论