Below is an implementation to narrow the graph width using a csscript
The command to copy your repo with the history reordered is
cs-script\cscs.exe HgSortMergeChangesets.cs fromRepo toNewRepo
The file "HgSortMergeChangesets.cs" has the following contents:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
class Program
{
static int Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("usage: SortHgRepo <fromRepo> <toRepo>");
return -1;
}
var fromRepo = new DirectoryInfo(args[0]);
var toRepo = new DirectoryInfo(args[1]);
int errorCode = VerifyParameters(toRepo, fromRepo);
if (errorCode != 0)
{
return errorCode;
}
var revsOutput = ExecCmdReturnStdOut("hg.exe", "log -r \"sort(merge(),date)\" -T \"{rev} {date|date}\\n\"", fromRepo.FullName, Console.WriteLine);
var mergeChangesets = ParseChangesetLog(revsOutput)
.ToList();
ExecCmdReturnStdOut("hg.exe", string.Format("clone -U -r 0 . \"{0}\"", toRepo.FullName), fromRepo.FullName, Console.WriteLine);
foreach (var changeset in mergeChangesets)
{
ExecCmdReturnStdOut("hg.exe", string.Format("pull \"{1}\" -r {0}", changeset.ChangesetId, fromRepo.FullName), toRepo.FullName, Console.WriteLine);
}
ExecCmdReturnStdOut("hg.exe", string.Format("pull \"{0}\"", fromRepo.FullName), toRepo.FullName, Console.WriteLine);
return 0;
}
private static int VerifyParameters(DirectoryInfo toRepo, DirectoryInfo fromRepo)
{
if (toRepo.Exists)
{
Console.WriteLine("The destination repo already exists: {0}", toRepo);
{
return -2;
}
}
if (!fromRepo.Exists)
{
Console.WriteLine("The source repo does not exists: {0}", fromRepo);
{
return -3;
}
}
// make sure the source dir is a repo
try
{
var identity = ExecCmdReturnStdOut("hg.exe", "identify", fromRepo.FullName, Console.WriteLine);
Console.WriteLine(identity);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine("The source directory, {0}, does not look like an Hg repo.", fromRepo);
return -4;
}
return 0;
}
private static IEnumerable<Changeset> ParseChangesetLog(string revsOutput)
{
using (var r = new StringReader(revsOutput))
{
string line;
while ((line = r.ReadLine()) != null)
{
var spacePos = line.IndexOf(' ');
yield return new Changeset
{
ChangesetId = int.Parse(line.Substring(0, spacePos)),
DateStr = line.Substring(spacePos + 1)
};
}
}
}
class Changeset
{
public int ChangesetId;
public string DateStr;
public DateTime Date { get { return DateTime.ParseExact(DateStr, "ddd MMM dd H:mm:ss yyyy zzz", null); } }
}
public static string ExecCmdReturnStdOut(string program, string args, string workingDir, Action<string> writeline)
{
writeline(String.Format("Executing: \"{0}\" {1} in {2}", program, args, workingDir));
using (var proc = new Process())
{
proc.StartInfo.Arguments = args;
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.FileName = program;
proc.StartInfo.WorkingDirectory = workingDir;
proc.StartInfo.RedirectStandardError = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
var output = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
if (proc.ExitCode != 0)
{
throw new Exception(string.Format("error code {0} returned when running command {1} in dir {2}", proc.ExitCode, "\"" + program + "\" " + args, workingDir));
}
return output;
}
}
}
hg rebase
instead ofhg merge
? – Janejanean