Skip to content

Instantly share code, notes, and snippets.

@qbikez
Created January 21, 2017 05:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qbikez/e900456032833fb2baaaee87e19a8ccd to your computer and use it in GitHub Desktop.
Save qbikez/e900456032833fb2baaaee87e19a8ccd to your computer and use it in GitHub Desktop.
Some powershell scripts helpful in mercurial repository conversion
original_branch_name new_branch_name
r:!hds to-remove # Spowoduje to zmian┼Ľ nazwy wszystkich branchy, kt╦çre nie pasujÔĽú do regexu `hds` na `to-remove`.
include path/to/file
exclude path/to/file
rename from/file to/file
include r:.*\.Core\..*/ # include directories with names matching "*.Core.*"
exclude r!:.*\MyProject\..*/ # exclude directories with names not matching "*.MyProject.*"
include sln:MyProject.Core/MyProject.Core.sln # include sln MyProject.Core/MyProject.Core.sln and all of its projects
param ([Parameter(Mandatory=$true)]$sln)
$content = get-content $sln
$csprojlines = $content | ? { $_ -match "\.csproj" -or $_ -match "\.xproj" }
$dir = split-path -parent $sln
$csprojs = $csprojlines | % {
if ($_ -match '^.* = "[^"]*", "(?<csprojpath>[^"]*)"') {
return $Matches["csprojpath"]
}
}
$csprojs = $csprojs | % {
return (join-path $dir $_)
} | % {
return (get-item $_).fullname
} | % {
return split-path -parent $_
}
$includes = $csprojs | % {
return (get-item $_).FullName
}
pushd
try {
cd $dir
}
finally {
popd
}
return $includes
[cmdletbinding(supportsshouldprocess)]
param(
[Parameter(mandatory=$true)]$src,
[Parameter(mandatory=$true)]$dest,
$desttype = "hg",
$filemap = "filemap.txt",
$branchmap = "branchmap.txt",
$srcbranch = $null,
[switch][bool] $force = $false,
[switch][bool] $append = $false,
$startrev = $null,
[switch][bool] $ignorerrors)
pushd
cd $PSScriptRoot
try {
import-module require
req pathutils
req deployment
req process
function generate-filemapentry($src, $srcpath, $destpath, $action = "include") {
$map = @()
if ($srcpath.startswith("r:") -or $srcpath.startswith("r:!")) {
if ($srcpath.startswith("r:!")) {
throw "path r:! not implemented"
}
elseif ($srcpath.startswith("r:")) {
$srcpath = $srcpath.substring("r:".Length)
$isdir = $false
if ($srcpath.endswith("/")) {
$isdir = $true
$srcpath = $srcpath.trimend("/")
}
# $srcpath = $srcpath -replace "/","\"
Get-Listing -Path $src -Excludes @(".hg/","dnx-packages/","node_modules/","packages/","bin/","obj/","testresults/") -Recurse `
-dirs:$isdir -include $srcpath | % {
$path = get-relativepath $src $_.FullName
$map += "$action ""$($path.replace("\","/"))"""
}
}
}
elseif ($srcpath.startswith("sln:")) {
$path = $srcpath.substring("sln:".Length)
$sln = (get-item (join-path $src $path)).FullName
$items = & "$psscriptroot\get-sln-items.ps1" -sln $sln
$items = $items | % { Get-RelativePath -from $src -to $_ } | % { "$action $($_.replace("\","/"))" }
return @($items) + @("$action $path")
}
else {
$map += "$action ""$($srcpath.replace("\","/"))"""
}
return $map
}
function filter-filemap ($map) {
$toremove = @()
$newmap = @()
# foreach($entry in $map) {
# $list += $entry
# }
# $map = $list
$hashmap = @{}
for($i = $map.Length - 1; $i -ge 0; $i--) {
$entry = $map[$i]
$space = $entry.indexof(" ")
$path = $entry.substring($space+1)
if ($hashmap[$path] -eq $null) {
$hashmap[$path] = @($i)
$newmap += $entry
} else {
# $path was already found. remove all other entries
$toremove += $i
}
}
# remove from the end to avoid index shift
# for($i = $toremove.length-1; $i -ge 0; $i--) {
# write-host "removing duplicate item '$($map[$i])' at pos $i"
# }
[Array]::Reverse($newmap)
return $newmap
}
function generate-branchmapentry($src, $srcbranch, $destbranch, $branches) {
pushd
try {
if ($srcbranch -eq "*") {
#$branches = $branches | % { $_.Split(" ")[0] }
$map = $branches | % { "$_ $destbranch" }
return $map
}
elseif ($srcbranch.startswith("r:") -or $srcbranch.startswith("r:!")) {
$map = @()
if ($srcbranch.startswith("r:!")) {
$srcbranch = $srcbranch.substring("r:!".Length)
$branches | % {
if ($_ -notmatch $srcbranch) {
if ($_ -match "\s") { $_ = """$_""" }
$map += "$_ $destbranch"
}
}
}
elseif ($srcbranch.startswith("r:")) {
$srcbranch = $srcbranch.substring("r:".Length)
$branches | % {
if ($_ -match $srcbranch) {
if ($_ -match "\s") { $_ = """$_""" }
$map += @("$_ $destbranch")
}
}
}
return $map
}
else {
return "$srcbranch $destbranch"
}
}
finally {
popd
}
}
if ($dest.endswith(".git")) {
$desttype = "git"
$dest = $dest.Replace(".git",".hg")
}
if ((test-path $dest) -and $force) {
invoke cmd /c rmdir $dest /S /Q
}
if (!(test-path $dest) -or $append)
{
if ($srcbranch -ne $null) {
pushd
try {
cd $src
hg update $srcbranch
if ($lastexitcode -ne 0) {
throw "failed to update to branch $srcbranch in $src"
}
} finally {
popd
}
}
#$content = $includePaths | % {
# "include ""$_"""
#}
#$content | Out-File $filemap -Encoding ascii
write-host "generating branchmap"
copy-item $branchmap "branchmap.gen.txt"
$branchmap = "branchmap.gen.txt"
$bmap = get-content $branchmap
pushd
try {
cd $src
$branches = hg branches -c
$branches = $branches | % {
$null = $_ -match "(?<name>.*?)\s+[0-9]+:"
$matches["name"]
}
} finally {
popd
}
$bmap = $bmap | % {
if ($_ -match "(?<src>.*) (?<dst>.*)") {
$generated = generate-branchmapentry $src $Matches["src"] $Matches["dst"] $branches
$generated
}
else {
$_
}
}
$bmap | out-file $branchmap -Encoding ascii
$processfilemap = $true
if (test-path "filemap.gen.txt") {
$gen = get-item "filemap.gen.txt"
$org = get-item $filemap
if ($org.LastWriteTimeUtc -le $gen.LastWriteTimeUtc) {
$processfilemap = $false
}
}
if ($processfilemap) {
write-host "generating filemap"
#copy-item $filemap "filemap.gen.txt"
$fmap = get-content $filemap
$filemap = "filemap.gen.txt"
pushd
$fmap = $fmap| % {
if ($_ -match "(?<action>include|exclude) (?<src>.*)") {
$generated = generate-filemapentry $src $Matches["src"] -action $Matches["action"]
$generated
}
else {
$_
}
}
$fmap = filter-filemap $fmap
$fmap | out-file $filemap -Encoding ascii
} else {
$filemap = "filemap.gen.txt"
}
write-host "converting"
$p = @(
"--config","extensions.hgext.convert="
"--dest-type","hg"
"--filemap",(get-item $filemap).FullName
"--branchmap",(get-item $branchmap).FullName
"--verbose"
"--full"
)
if ($startrev -ne $null) {
$p += "--config","convert.hg.startrev=$startrev"
}
if ($ignorerrors){
$p += "--config","convert.hg.ignoreerrors=True"
}
$p += $src,$dest
write-host "executing:"
Write-Host "hg convert $p"
$converted = $false
if ($PSCmdlet.ShouldProcess("running hg convert")) {
invoke hg convert @p -verbose
$converted = $true
}
push-location
try {
if (test-path $dest) {
cd $dest
invoke hg sum
invoke hg status
invoke hg log
}
} finally {
pop-location
}
} else {
write-warning "$dest already exists. not doing hg convert"
}
if ($desttype -eq "git") {
.\hg2git.ps1 -src $dest -force:$force
}
}
finally {
popd
}
[cmdletbinding(supportsshouldprocess)]
param(
[Parameter(mandatory=$true)]$src,
[Parameter(mandatory=$true)]$dest,
$desttype = "git",
[switch][bool]$force = $true,
$fastexport = $null
)
ipmo require
req process
if ($fastexpor -eq $null) { $fastexport = "$psscriptroot\fast-export\hg-fast-export.py" }
if ((test-path $dest) -and $force) {
remove-item $dest -Recurse -Force
}
if (!(test-path $dest))
{
& "$psscriptroot\hg-convert.ps1" @PSBoundParameters
}
if ($desttype -eq "git") {
# export
$PYTHON = "python"
$GIT_DIR = ".git"
push-location
try {
$gitdst = "$dest.git"
if (test-path $gitdst) { remove-item $gitdst -Recurse -Force }
$null = new-item $gitdst -type directory
cd $gitdst
git init
#python hg-fast-export.py -r src\repo.h --marks .git\marks.txt --mapping .git\mapping.txt --heads .git\heads.txt --status .git\status.txt
# python hg-fast-export.py -r src\repo.hg --marks .git\marks.txt --mapping .git\mapping.txt --heads .git\heads.txt --status .\git\status.txt
<# $result = & $PYTHON $fastexport --repo $dest `
--marks "$GIT_DIR/git-marks.txt" `
--mapping "$GIT_DIR/git-mapping.txt" `
--heads "$GIT_DIR/git-heads.txt" `
--status "$GIT_DIR/git-status.txt"
$resultpath = "$GIT_DIR/fast-import.txt"
$result | Out-File $resultpath -Encoding ascii
$resultfile = gi $resultpath
$result | & git fast-import --export-marks="$GIT_DIR/git-export-marks.txt"#>
invoke -useShellExecute python @(
"$fastexport"
"-r","$dest"
"--marks",".git\marks.txt"
"--mapping",".git\mapping.txt"
"--heads",".git\heads.txt"
"--status",".git\status.txt"
"--force"
"> .git\fast-export.txt"
invoke -useShellExecute git @(
"fast-import"
"< .git\fast-export.txt"
)
git log
} finally {
pop-location
}
}
param(
[Parameter(Mandatory=$true)]$src,
[Parameter(Mandatory=$false)]$python = "python",
[Parameter(Mandatory=$false)]$fastexport = "fast-export",
[switch][bool] $force = $false
)
pushd
try {
ipmo require
req process
$srcfull = (get-item $src).FullName
cd $PSScriptRoot
if (!(test-path $fastexport)) {
& git clone https://github.com/frej/fast-export $fastexport 2>&1
}
$fastexport = (get-item $fastexport).FullName
$dest = $srcfull.Replace(".hg",".git")
if (!$dest.Contains("git")) { $dest = $dest + ".git" }
if (test-path $dest) {
if ($force) {
write-warning "-force specified. removing $dest"
cmd /c rmdir /S /Q $dest
}
else {
write-warning "$dest already exists. not doing anything"
return
}
}
mkdir $dest
cd $dest
git init .
try {
if (test-path git-fast-import.src) {
rm git-fast-import.src
}
invoke -useshellexecute $python "$fastexport\hg-fast-export.py -r $src --marks=marks.txt --mapping=mapping.txt --heads=heads.txt --status=status.txt > git-fast-import.src" -Verbose
} catch {
if (test-path git-fast-import.src) {
$msg = get-content git-fast-import.src
throw $msg
} else {
throw
}
}
invoke -useshellexecute git "fast-import --export-marks=marks.txt.tmp < git-fast-import.src" -Verbose
} finally {
popd
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment