private static ExitCodes OnGetCommitsCommand(string projectPath, string version, bool quiet)
        {
            if (!Version.TryParse(version, out Version parsedVersion))
            {
                Console.Error.WriteLine($"\"{version}\" is not a simple a.b.c[.d] version spec.");
                return(ExitCodes.InvalidVersionSpec);
            }

            string searchPath = GetSpecifiedOrCurrentDirectoryPath(projectPath);

            var repository = GitExtensions.OpenGitRepo(searchPath);

            if (repository == null)
            {
                Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath);
                return(ExitCodes.NoGitRepo);
            }

            string repoRelativeProjectDir = GetRepoRelativePath(searchPath, repository);
            var    candidateCommits       = GitExtensions.GetCommitsFromVersion(repository, parsedVersion, repoRelativeProjectDir).ToList();

            PrintCommits(quiet, searchPath, repository, candidateCommits);

            return(ExitCodes.OK);
        }
        private static ExitCodes OnTagCommand(string projectPath, string versionOrRef)
        {
            if (string.IsNullOrEmpty(versionOrRef))
            {
                versionOrRef = DefaultRef;
            }

            string searchPath = GetSpecifiedOrCurrentDirectoryPath(projectPath);

            var repository = GitExtensions.OpenGitRepo(searchPath);

            if (repository == null)
            {
                Console.Error.WriteLine("No git repo found at or above: \"{0}\"", searchPath);
                return(ExitCodes.NoGitRepo);
            }

            LibGit2Sharp.GitObject refObject = null;
            try
            {
                repository.RevParse(versionOrRef, out var reference, out refObject);
            }
            catch (LibGit2Sharp.NotFoundException) { }

            var commit = refObject as LibGit2Sharp.Commit;

            if (commit == null)
            {
                if (!Version.TryParse(versionOrRef, out Version parsedVersion))
                {
                    Console.Error.WriteLine($"\"{versionOrRef}\" is not a simple a.b.c[.d] version spec or git reference.");
                    return(ExitCodes.InvalidVersionSpec);
                }

                string repoRelativeProjectDir = GetRepoRelativePath(searchPath, repository);
                var    candidateCommits       = GitExtensions.GetCommitsFromVersion(repository, parsedVersion, repoRelativeProjectDir).ToList();
                if (candidateCommits.Count == 0)
                {
                    Console.Error.WriteLine("No commit with that version found.");
                    return(ExitCodes.NoMatchingVersion);
                }
                else if (candidateCommits.Count > 1)
                {
                    PrintCommits(false, searchPath, repository, candidateCommits, includeOptions: true);
                    int selection;
                    do
                    {
                        Console.Write("Enter selection: ");
                    }while (!int.TryParse(Console.ReadLine(), out selection) || selection > candidateCommits.Count || selection < 1);
                    commit = candidateCommits[selection - 1];
                }
                else
                {
                    commit = candidateCommits.Single();
                }
            }

            var oracle = new VersionOracle(searchPath, repository, commit, CloudBuild.Active);

            if (!oracle.VersionFileFound)
            {
                Console.Error.WriteLine("No version.json file found in or above \"{0}\" in commit {1}.", searchPath, commit.Sha);
                return(ExitCodes.NoVersionJsonFound);
            }

            oracle.PublicRelease = true; // assume a public release so we don't get a redundant -gCOMMITID in the tag name
            string tagName = $"v{oracle.SemVer2}";

            try
            {
                repository.Tags.Add(tagName, commit);
            }
            catch (LibGit2Sharp.NameConflictException)
            {
                var  taggedCommit = repository.Tags[tagName].Target as LibGit2Sharp.Commit;
                bool correctTag   = taggedCommit?.Sha == commit.Sha;
                Console.Error.WriteLine("The tag {0} is already defined ({1}).", tagName, correctTag ? "to the right commit" : $"expected {commit.Sha} but was on {taggedCommit.Sha}");
                return(correctTag ? ExitCodes.OK : ExitCodes.TagConflict);
            }

            Console.WriteLine("{0} tag created at {1}.", tagName, commit.Sha);
            Console.WriteLine("Remember to push to a remote: git push origin {0}", tagName);

            return(ExitCodes.OK);
        }