Beispiel #1
0
	public static void Main (string[] args)
	{
		string[] benchmarkNames = null;
		//var pausetime = false;
		var timeout = -1;
		string commitFromCmdline = null;
		string gitRepoDir = null;
		string rootFromCmdline = null;
		string buildURL = null;
		string logURL = null;
		string pullRequestURL = null;
		string monoRepositoryPath = null;
		string runSetId = null;
		string configFile = null;
		bool justCreateRunSet = false;
		bool justListBenchmarks = false;

		var optindex = 0;

		for (; optindex < args.Length; ++optindex) {
			if (args [optindex] == "-b" || args [optindex] == "--benchmarks") {
				var newNames = args [++optindex].Split (',').Select (s => s.Trim ());
				if (benchmarkNames == null)
					benchmarkNames = newNames.ToArray ();
				else
					benchmarkNames = newNames.Union (benchmarkNames).ToArray ();
			} else if (args [optindex] == "-c" || args [optindex] == "--config-file") {
				configFile = args [++optindex];
			} else if (args [optindex] == "-l" || args [optindex] == "--list-benchmarks") {
				justListBenchmarks = true;
			} else if (args [optindex] == "--commit") {
				commitFromCmdline = args [++optindex];
			} else if (args [optindex] == "--git-repo") {
				gitRepoDir = args [++optindex];
			} else if (args [optindex] == "--build-url") {
				buildURL = args [++optindex];
			} else if (args [optindex] == "--log-url") {
				logURL = args [++optindex];
			} else if (args [optindex] == "--pull-request-url") {
				pullRequestURL = args [++optindex];
			} else if (args [optindex] == "--mono-repository") {
				monoRepositoryPath = args [++optindex];
			} else if (args [optindex] == "--create-run-set") {
				justCreateRunSet = true;
			} else if (args [optindex] == "--run-set-id") {
				runSetId = args [++optindex];
			} else if (args [optindex] == "--root") {
				rootFromCmdline = args [++optindex];
			} else if (args [optindex] == "-t" || args [optindex] == "--timeout") {
				timeout = Int32.Parse (args [++optindex]);
				timeout = timeout <= 0 ? -1 : timeout;
			// } else if (args [optindex] == "-p" || args [optindex] == "--pause-time") {
			// 	pausetime = Boolean.Parse (args [++optindex]);
			} else if (args [optindex].StartsWith ("--help")) {
				UsageAndExit ();
			} else if (args [optindex] == "--") {
				optindex += 1;
				break;
			} else if (args [optindex].StartsWith ("-")) {
				Console.Error.WriteLine ("unknown parameter {0}", args [optindex]);
				UsageAndExit ();
			} else {
				break;
			}
		}

		if (justCreateRunSet && runSetId != null) {
			Console.Error.WriteLine ("Error: --create-run-set and --run-set-id are incompatible.");
			Environment.Exit (1);
		}

		if (justListBenchmarks && benchmarkNames != null) {
			Console.Error.WriteLine ("Error: -b/--benchmarks and -l/--list-benchmarks are incompatible.");
			Environment.Exit (1);
		}

		string testsDir, benchmarksDir, machinesDir;

		if (args.Length - optindex == 4) {
			if (configFile != null) {
				Console.Error.WriteLine ("Error: You must not specify the config file twice.");
				Environment.Exit (1);
			}

			testsDir = args [optindex++];
			benchmarksDir = args [optindex++];
			machinesDir = args [optindex++];
			configFile = args [optindex++];
		} else if (args.Length - optindex == 0) {
			var exeLocation = System.Reflection.Assembly.GetEntryAssembly ().Location;
			var exeName = Path.GetFileName (exeLocation);
			var exeDir = Path.GetDirectoryName (exeLocation);
			if (exeName != "compare.exe") {
				Console.Error.WriteLine ("Error: Executable is not `compare.exe`.  Please specify all paths manually.");
				Environment.Exit (1);
			}
			if (Path.GetFileName (exeDir) != "tools") {
				Console.Error.WriteLine ("Error: Executable is not in the `tools` directory.  Please specify all paths manually.");
				Environment.Exit (1);
			}
			var root = Path.GetDirectoryName (exeDir);

			testsDir = Path.Combine (root, "tests");
			benchmarksDir = Path.Combine (root, "benchmarks");
			machinesDir = Path.Combine (root, "machines");

			if (configFile == null)
				configFile = Path.Combine (root, "configs", "default-sgen.conf");
		} else {
			UsageAndExit (null, 1);
			return;
		}

		var benchmarks = Benchmark.LoadAllFrom (benchmarksDir, benchmarkNames);
		if (benchmarks == null) {
			Console.WriteLine ("Error: Could not load all benchmarks.");
			Environment.Exit (1);
		}

		if (justListBenchmarks) {
			foreach (var benchmark in benchmarks.OrderBy (b => b.Name)) {
				Console.Out.WriteLine (benchmark.Name);
			}
			Environment.Exit (0);
		}

		var gitHubClient = GitHubInterface.GitHubClient;

		if (!ParseInterface.Initialize ()) {
			Console.Error.WriteLine ("Error: Could not initialize Parse interface.");
			Environment.Exit (1);
		}

		var config = Config.LoadFrom (configFile, rootFromCmdline);

		var machine = Machine.LoadCurrentFrom (machinesDir);

		var commit = AsyncContext.Run (() => config.GetCommit (commitFromCmdline, gitRepoDir));

		if (commit == null) {
			Console.WriteLine ("Error: Could not get commit");
			Environment.Exit (1);
		}
		if (commit.CommitDate == null) {
			Console.WriteLine ("Error: Could not get a commit date.");
			Environment.Exit (1);
		}

		RunSet runSet;
		if (runSetId != null) {
			if (pullRequestURL != null) {
				Console.WriteLine ("Error: Pull request URL cannot be specified for an existing run set.");
				Environment.Exit (1);
			}
			runSet = AsyncContext.Run (() => RunSet.FromId (runSetId, config, commit, buildURL, logURL));
			if (runSet == null) {
				Console.WriteLine ("Error: Could not get run set.");
				Environment.Exit (1);
			}
		} else {
			ParseObject pullRequestBaselineRunSet = null;

			if (pullRequestURL != null) {
				if (monoRepositoryPath == null) {
					Console.Error.WriteLine ("Error: Must specify a mono repository path to test a pull request.");
					Environment.Exit (1);
				}

				var repo = new Benchmarker.Common.Git.Repository (monoRepositoryPath);

				pullRequestBaselineRunSet = AsyncContext.Run (() => GetPullRequestBaselineRunSet (pullRequestURL, repo, config));
			}

			runSet = new RunSet {
				StartDateTime = DateTime.Now,
				Config = config,
				Commit = commit,
				BuildURL = buildURL,
				LogURL = logURL,
				PullRequestURL = pullRequestURL,
				PullRequestBaselineRunSet = pullRequestBaselineRunSet
			};
		}

		if (!justCreateRunSet) {
			var someSuccess = false;

			foreach (var benchmark in benchmarks.OrderBy (b => b.Name)) {
				/* Run the benchmarks */
				if (config.Count <= 0)
					throw new ArgumentOutOfRangeException (String.Format ("configs [\"{0}\"].Count <= 0", config.Name));

				Console.Out.WriteLine ("Running benchmark \"{0}\" with config \"{1}\"", benchmark.Name, config.Name);

				var runner = new Runner (testsDir, config, benchmark, machine, timeout);

				var result = new Result {
					DateTime = DateTime.Now,
					Benchmark = benchmark,
					Config = config,
				};

				var haveTimedOut = false;
				var haveCrashed = false;

				for (var i = 0; i < config.Count + 1; ++i) {
					bool timedOut;

					Console.Out.Write ("\t\t-> {0} ", i == 0 ? "[dry run]" : String.Format ("({0}/{1})", i, config.Count));

					var run = runner.Run (out timedOut);

					// skip first one
					if (i == 0)
						continue;

					if (run != null) {
						result.Runs.Add (run);
						someSuccess = true;
					} else {
						if (timedOut)
							haveTimedOut = true;
						else
							haveCrashed = true;
					}
				}

				if (haveTimedOut)
					runSet.TimedOutBenchmarks.Add (benchmark);
				if (haveCrashed)
					runSet.CrashedBenchmarks.Add (benchmark);

				// FIXME: implement pausetime
				//if (pausetime)
				//	throw new NotImplementedException ();

				runSet.Results.Add (result);
			}

			if (!someSuccess)
				Console.WriteLine ("all runs failed.");
		}
		
		runSet.FinishDateTime = DateTime.Now;

		Console.WriteLine ("uploading");
		try {
			var parseObject = AsyncContext.Run (() => runSet.UploadToParse ());
			Console.WriteLine ("http://xamarin.github.io/benchmarker/front-end/runset.html#{0}", parseObject.ObjectId);
			ParseObject pullRequestObject = null;
			if (pullRequestURL != null) {
				pullRequestObject = parseObject.Get<ParseObject> ("pullRequest");
                Console.WriteLine ("http://xamarin.github.io/benchmarker/front-end/pullrequest.html#{0}", pullRequestObject.ObjectId);
			}
			Console.Write ("{{ \"runSetId\": \"{0}\"", parseObject.ObjectId);
            if (pullRequestURL != null)
                Console.Write (", \"pullRequestId\": \"{0}\"", pullRequestObject.ObjectId);
            Console.WriteLine (" }");
		} catch (Exception exc) {
			Console.WriteLine ("Error: Failure uploading data: " + exc);
			Environment.Exit (1);
		}
	}
Beispiel #2
0
    public static void Main(string[] args)
    {
        string[] benchmarkNames = null;
        //var pausetime = false;
        var    timeout            = -1;
        string commitFromCmdline  = null;
        string gitRepoDir         = null;
        string rootFromCmdline    = null;
        string buildURL           = null;
        string logURL             = null;
        string pullRequestURL     = null;
        string monoRepositoryPath = null;
        string runSetId           = null;
        string configFile         = null;
        bool   justCreateRunSet   = false;
        bool   justListBenchmarks = false;

        var optindex = 0;

        for (; optindex < args.Length; ++optindex)
        {
            if (args [optindex] == "-b" || args [optindex] == "--benchmarks")
            {
                var newNames = args [++optindex].Split(',').Select(s => s.Trim());
                if (benchmarkNames == null)
                {
                    benchmarkNames = newNames.ToArray();
                }
                else
                {
                    benchmarkNames = newNames.Union(benchmarkNames).ToArray();
                }
            }
            else if (args [optindex] == "-c" || args [optindex] == "--config-file")
            {
                configFile = args [++optindex];
            }
            else if (args [optindex] == "-l" || args [optindex] == "--list-benchmarks")
            {
                justListBenchmarks = true;
            }
            else if (args [optindex] == "--commit")
            {
                commitFromCmdline = args [++optindex];
            }
            else if (args [optindex] == "--git-repo")
            {
                gitRepoDir = args [++optindex];
            }
            else if (args [optindex] == "--build-url")
            {
                buildURL = args [++optindex];
            }
            else if (args [optindex] == "--log-url")
            {
                logURL = args [++optindex];
            }
            else if (args [optindex] == "--pull-request-url")
            {
                pullRequestURL = args [++optindex];
            }
            else if (args [optindex] == "--mono-repository")
            {
                monoRepositoryPath = args [++optindex];
            }
            else if (args [optindex] == "--create-run-set")
            {
                justCreateRunSet = true;
            }
            else if (args [optindex] == "--run-set-id")
            {
                runSetId = args [++optindex];
            }
            else if (args [optindex] == "--root")
            {
                rootFromCmdline = args [++optindex];
            }
            else if (args [optindex] == "-t" || args [optindex] == "--timeout")
            {
                timeout = Int32.Parse(args [++optindex]);
                timeout = timeout <= 0 ? -1 : timeout;
                // } else if (args [optindex] == "-p" || args [optindex] == "--pause-time") {
                //  pausetime = Boolean.Parse (args [++optindex]);
            }
            else if (args [optindex].StartsWith("--help"))
            {
                UsageAndExit();
            }
            else if (args [optindex] == "--")
            {
                optindex += 1;
                break;
            }
            else if (args [optindex].StartsWith("-"))
            {
                Console.Error.WriteLine("unknown parameter {0}", args [optindex]);
                UsageAndExit();
            }
            else
            {
                break;
            }
        }

        if (justCreateRunSet && runSetId != null)
        {
            Console.Error.WriteLine("Error: --create-run-set and --run-set-id are incompatible.");
            Environment.Exit(1);
        }

        if (justListBenchmarks && benchmarkNames != null)
        {
            Console.Error.WriteLine("Error: -b/--benchmarks and -l/--list-benchmarks are incompatible.");
            Environment.Exit(1);
        }

        string testsDir, benchmarksDir, machinesDir;

        if (args.Length - optindex == 4)
        {
            if (configFile != null)
            {
                Console.Error.WriteLine("Error: You must not specify the config file twice.");
                Environment.Exit(1);
            }

            testsDir      = args [optindex++];
            benchmarksDir = args [optindex++];
            machinesDir   = args [optindex++];
            configFile    = args [optindex++];
        }
        else if (args.Length - optindex == 0)
        {
            var exeLocation = System.Reflection.Assembly.GetEntryAssembly().Location;
            var exeName     = Path.GetFileName(exeLocation);
            var exeDir      = Path.GetDirectoryName(exeLocation);
            if (exeName != "compare.exe")
            {
                Console.Error.WriteLine("Error: Executable is not `compare.exe`.  Please specify all paths manually.");
                Environment.Exit(1);
            }
            if (Path.GetFileName(exeDir) != "tools")
            {
                Console.Error.WriteLine("Error: Executable is not in the `tools` directory.  Please specify all paths manually.");
                Environment.Exit(1);
            }
            var root = Path.GetDirectoryName(exeDir);

            testsDir      = Path.Combine(root, "tests");
            benchmarksDir = Path.Combine(root, "benchmarks");
            machinesDir   = Path.Combine(root, "machines");

            if (configFile == null)
            {
                configFile = Path.Combine(root, "configs", "default-sgen.conf");
            }
        }
        else
        {
            UsageAndExit(null, 1);
            return;
        }

        var benchmarks = Benchmark.LoadAllFrom(benchmarksDir, benchmarkNames);

        if (benchmarks == null)
        {
            Console.WriteLine("Error: Could not load all benchmarks.");
            Environment.Exit(1);
        }

        if (justListBenchmarks)
        {
            foreach (var benchmark in benchmarks.OrderBy(b => b.Name))
            {
                Console.Out.WriteLine(benchmark.Name);
            }
            Environment.Exit(0);
        }

        var gitHubClient = GitHubInterface.GitHubClient;

        if (!ParseInterface.Initialize())
        {
            Console.Error.WriteLine("Error: Could not initialize Parse interface.");
            Environment.Exit(1);
        }

        var config = Config.LoadFrom(configFile, rootFromCmdline);

        var machine = Machine.LoadCurrentFrom(machinesDir);

        var commit = AsyncContext.Run(() => config.GetCommit(commitFromCmdline, gitRepoDir));

        if (commit == null)
        {
            Console.WriteLine("Error: Could not get commit");
            Environment.Exit(1);
        }
        if (commit.CommitDate == null)
        {
            Console.WriteLine("Error: Could not get a commit date.");
            Environment.Exit(1);
        }

        RunSet runSet;

        if (runSetId != null)
        {
            if (pullRequestURL != null)
            {
                Console.WriteLine("Error: Pull request URL cannot be specified for an existing run set.");
                Environment.Exit(1);
            }
            runSet = AsyncContext.Run(() => RunSet.FromId(runSetId, config, commit, buildURL, logURL));
            if (runSet == null)
            {
                Console.WriteLine("Error: Could not get run set.");
                Environment.Exit(1);
            }
        }
        else
        {
            ParseObject pullRequestBaselineRunSet = null;

            if (pullRequestURL != null)
            {
                if (monoRepositoryPath == null)
                {
                    Console.Error.WriteLine("Error: Must specify a mono repository path to test a pull request.");
                    Environment.Exit(1);
                }

                var repo = new Benchmarker.Common.Git.Repository(monoRepositoryPath);

                pullRequestBaselineRunSet = AsyncContext.Run(() => GetPullRequestBaselineRunSet(pullRequestURL, repo, config));
            }

            runSet = new RunSet {
                StartDateTime             = DateTime.Now,
                Config                    = config,
                Commit                    = commit,
                BuildURL                  = buildURL,
                LogURL                    = logURL,
                PullRequestURL            = pullRequestURL,
                PullRequestBaselineRunSet = pullRequestBaselineRunSet
            };
        }

        if (!justCreateRunSet)
        {
            var someSuccess = false;

            foreach (var benchmark in benchmarks.OrderBy(b => b.Name))
            {
                /* Run the benchmarks */
                if (config.Count <= 0)
                {
                    throw new ArgumentOutOfRangeException(String.Format("configs [\"{0}\"].Count <= 0", config.Name));
                }

                Console.Out.WriteLine("Running benchmark \"{0}\" with config \"{1}\"", benchmark.Name, config.Name);

                var runner = new Runner(testsDir, config, benchmark, machine, timeout);

                var result = new Result {
                    DateTime  = DateTime.Now,
                    Benchmark = benchmark,
                    Config    = config,
                };

                var haveTimedOut = false;
                var haveCrashed  = false;

                for (var i = 0; i < config.Count + 1; ++i)
                {
                    bool timedOut;

                    Console.Out.Write("\t\t-> {0} ", i == 0 ? "[dry run]" : String.Format("({0}/{1})", i, config.Count));

                    var run = runner.Run(out timedOut);

                    // skip first one
                    if (i == 0)
                    {
                        continue;
                    }

                    if (run != null)
                    {
                        result.Runs.Add(run);
                        someSuccess = true;
                    }
                    else
                    {
                        if (timedOut)
                        {
                            haveTimedOut = true;
                        }
                        else
                        {
                            haveCrashed = true;
                        }
                    }
                }

                if (haveTimedOut)
                {
                    runSet.TimedOutBenchmarks.Add(benchmark);
                }
                if (haveCrashed)
                {
                    runSet.CrashedBenchmarks.Add(benchmark);
                }

                // FIXME: implement pausetime
                //if (pausetime)
                //	throw new NotImplementedException ();

                runSet.Results.Add(result);
            }

            if (!someSuccess)
            {
                Console.WriteLine("all runs failed.");
            }
        }

        runSet.FinishDateTime = DateTime.Now;

        Console.WriteLine("uploading");
        try {
            var parseObject = AsyncContext.Run(() => runSet.UploadToParse());
            Console.WriteLine("http://xamarin.github.io/benchmarker/front-end/runset.html#{0}", parseObject.ObjectId);
            ParseObject pullRequestObject = null;
            if (pullRequestURL != null)
            {
                pullRequestObject = parseObject.Get <ParseObject> ("pullRequest");
                Console.WriteLine("http://xamarin.github.io/benchmarker/front-end/pullrequest.html#{0}", pullRequestObject.ObjectId);
            }
            Console.Write("{{ \"runSetId\": \"{0}\"", parseObject.ObjectId);
            if (pullRequestURL != null)
            {
                Console.Write(", \"pullRequestId\": \"{0}\"", pullRequestObject.ObjectId);
            }
            Console.WriteLine(" }");
        } catch (Exception exc) {
            Console.WriteLine("Error: Failure uploading data: " + exc);
            Environment.Exit(1);
        }
    }
Beispiel #3
0
    static async Task <ParseObject> GetPullRequestBaselineRunSet(string pullRequestURL, Benchmarker.Common.Git.Repository repository, Config config)
    {
        var gitHubClient = GitHubInterface.GitHubClient;
        var match        = Regex.Match(pullRequestURL, @"^https?://github\.com/mono/mono/pull/(\d+)/?$");

        if (match == null)
        {
            Console.WriteLine("Error: Cannot parse pull request URL.");
            Environment.Exit(1);
        }
        var pullRequestNumber = Int32.Parse(match.Groups [1].Value);

        Console.WriteLine("pull request {0}", pullRequestNumber);

        var pullRequest = await gitHubClient.PullRequest.Get("mono", "mono", pullRequestNumber);

        var prRepo   = pullRequest.Head.Repository.SshUrl;
        var prBranch = pullRequest.Head.Ref;

        var prSha = repository.Fetch(prRepo, prBranch);

        if (prSha == null)
        {
            Console.Error.WriteLine("Error: Could not fetch pull request branch {0} from repo {1}", prBranch, prRepo);
            Environment.Exit(1);
        }

        var masterSha = repository.Fetch("[email protected]:mono/mono.git", "master");

        if (masterSha == null)
        {
            Console.Error.WriteLine("Error: Could not fetch master.");
            Environment.Exit(1);
        }

        var baseSha = repository.MergeBase(prSha, masterSha);

        if (baseSha == null)
        {
            Console.Error.WriteLine("Error: Could not determine merge base of pull request.");
            Environment.Exit(1);
        }

        Console.WriteLine("Merge base sha is {0}", baseSha);

        var revList = repository.RevList(baseSha);

        if (revList == null)
        {
            Console.Error.WriteLine("Error: Could not get rev-list for merge base {0}.", baseSha);
            Environment.Exit(1);
        }
        Console.WriteLine("{0} commits in rev-list", revList.Length);

        var configObj = await config.GetFromParse();

        if (configObj == null)
        {
            Console.Error.WriteLine("Error: The config does not exist.");
            Environment.Exit(1);
        }

        var machineObj = await RunSet.GetMachineFromParse();

        if (machineObj == null)
        {
            Console.Error.WriteLine("Error: The machine does not exist.");
            Environment.Exit(1);
        }

        var runSets = await ParseInterface.PageQueryWithRetry(() => ParseObject.GetQuery ("RunSet")
                                                              .WhereEqualTo ("machine", machineObj)
                                                              .WhereEqualTo ("config", configObj)
                                                              .WhereDoesNotExist ("pullRequest")
                                                              .Include("commit"));

        Console.WriteLine("{0} run sets", runSets.Count());

        var runSetsByCommits = new Dictionary <string, ParseObject> ();

        foreach (var runSet in runSets)
        {
            var sha = runSet.Get <ParseObject> ("commit").Get <string> ("hash");
            if (runSetsByCommits.ContainsKey(sha))
            {
                // FIXME: select between them?
                continue;
            }
            runSetsByCommits.Add(sha, runSet);
        }

        foreach (var sha in revList)
        {
            if (runSetsByCommits.ContainsKey(sha))
            {
                Console.WriteLine("tested base commit is {0}", sha);
                return(runSetsByCommits [sha]);
            }
        }

        return(null);
    }
Beispiel #4
0
		public async Task<Commit> GetCommit (string optionalCommitHash, string optionalGitRepoDir)
		{
			if (NoMono) {
				// FIXME: return a dummy commit
				return null;
			}

			var info = NewProcessStartInfo ();
			/* Run without timing with --version */
			info.Arguments = "--version";

			Console.Out.WriteLine ("\t$> {0} {1} {2}", PrintableEnvironmentVariables (info), info.FileName, info.Arguments);

			var process = Process.Start (info);
			var version = Task.Run (() => new StreamReader (process.StandardOutput.BaseStream).ReadToEnd ()).Result;
			var versionError = Task.Run (() => new StreamReader (process.StandardError.BaseStream).ReadToEnd ()).Result;

			process.WaitForExit ();
			process.Close ();

			var line = version.Split (new char[] {'\n'}, 2) [0];
			var regex = new Regex ("^Mono JIT.*\\((.*)/([0-9a-f]+) (.*)\\)");
			var match = regex.Match (line);

			var commit = new Commit ();

			if (match.Success) {
				commit.Branch = match.Groups [1].Value;
				commit.Hash = match.Groups [2].Value;
				var date = match.Groups [3].Value;
				Console.WriteLine ("branch: " + commit.Branch + " hash: " + commit.Hash + " date: " + date);
			} else {
				if (optionalCommitHash == null) {
					Console.Error.WriteLine ("Error: cannot parse mono version and no commit given.");
					return null;
				}
			}

			if (commit.Branch == "(detached")
				commit.Branch = null;

			if (optionalCommitHash != null) {
				if (commit.Hash != null && !optionalCommitHash.StartsWith (commit.Hash)) {
					Console.Error.WriteLine ("Error: Commit hash specified on command line does not match the one reported with --version.");
					return null;
				}
				commit.Hash = optionalCommitHash;
			}

			try {
				var gitRepoDir = optionalGitRepoDir ?? Path.GetDirectoryName (Mono);
				var repo = new Repository (gitRepoDir);
				var gitHash = repo.RevParse (commit.Hash);
				if (gitHash == null) {
					Console.WriteLine ("Could not get commit " + commit.Hash + " from repository");
				} else {
					Console.WriteLine ("Got commit " + gitHash + " from repository");

					if (optionalCommitHash != null && optionalCommitHash != gitHash) {
						Console.Error.WriteLine ("Error: Commit hash specified on command line does not match the one from the git repository.");
						return null;
					}

					commit.Hash = gitHash;
					commit.MergeBaseHash = repo.MergeBase (commit.Hash, "master");
					commit.CommitDate = repo.CommitDate (commit.Hash);

					if (commit.CommitDate == null) {
						Console.Error.WriteLine ("Error: Could not get commit date from the git repository.");
						return null;
					}

					Console.WriteLine ("Commit {0} merge base {1} date {2}", commit.Hash, commit.MergeBaseHash, commit.CommitDate);
				}
			} catch (Exception) {
				Console.WriteLine ("Could not get git repository");
			}

			Octokit.Commit gitHubCommit = null;
			try {
				var gitHubClient = GitHubInterface.GitHubClient;
				gitHubCommit = await ParseInterface.RunWithRetry (() => gitHubClient.GitDatabase.Commit.Get ("mono", "mono", commit.Hash), typeof (Octokit.NotFoundException));
			} catch (Octokit.NotFoundException) {
				Console.WriteLine ("Commit " + commit.Hash + " not found on GitHub");
			}
			if (gitHubCommit == null) {
				Console.WriteLine ("Could not get commit " + commit.Hash + " from GitHub");
			} else {
				if (optionalCommitHash != null && optionalCommitHash != gitHubCommit.Sha) {
					Console.Error.WriteLine ("Error: Commit hash specified on command line does not match the one from GitHub.");
					return null;
				}

				commit.Hash = gitHubCommit.Sha;
				if (commit.CommitDate == null)
					commit.CommitDate = gitHubCommit.Committer.Date.DateTime;
				Console.WriteLine ("Got commit " + commit.Hash + " from GitHub");
			}

			return commit;
		}