Esempio n. 1
0
    public void PrepareRelease_JsonOutputWhenUpdatingReleaseBranch()
    {
        // create and configure repository
        this.InitializeSourceControl();

        // create version.json
        var versionOptions = new VersionOptions()
        {
            Version = SemanticVersion.Parse("1.0"),
            Release = new ReleaseOptions()
            {
                BranchName       = "v{version}",
                VersionIncrement = ReleaseVersionIncrement.Minor
            }
        };

        this.WriteVersionFile(versionOptions);
        var branchName = "v1.0";

        // switch to release branch
        Commands.Checkout(this.Repo, this.Repo.CreateBranch(branchName));

        // run release preparation
        var stdout         = new StringWriter();
        var releaseManager = new ReleaseManager(stdout);

        releaseManager.PrepareRelease(this.RepoPath, outputMode: ReleaseManager.ReleaseManagerOutputMode.Json);


        // Expected output:
        // {
        //     "CurrentBranch" : {
        //         "Name" : "<NAME>",
        //         "Commit" : "<COMMIT>",
        //         "Version" : "<VERSION>",
        //     },
        //     "NewBranch" : null
        // }

        var jsonOutput = JObject.Parse(stdout.ToString());

        // check "CurrentBranch"  output
        {
            var expectedCommitId = this.Repo.Branches[branchName].Tip.Sha;
            var expectedVersion  = VersionFile.GetVersion(this.Repo.Branches[branchName].Tip).Version.ToString();

            var currentBranchOutput = jsonOutput.Property("CurrentBranch")?.Value as JObject;
            Assert.NotNull(currentBranchOutput);

            Assert.Equal(branchName, currentBranchOutput.GetValue("Name")?.ToString());
            Assert.Equal(expectedCommitId, currentBranchOutput.GetValue("Commit")?.ToString());
            Assert.Equal(expectedVersion, currentBranchOutput.GetValue("Version")?.ToString());
        }
        // Check "NewBranch" output
        {
            // no new branch was created, so "NewBranch" should be null
            var newBranchOutput = jsonOutput.Property("NewBranch")?.Value as JObject;
            Assert.Null(newBranchOutput);
        }
    }
    public void SetVersion_PathFilters_InheritRelativePaths()
    {
        this.InitializeSourceControl();

        var rootVersionOptions = new VersionOptions
        {
            Version     = SemanticVersion.Parse("1.2"),
            PathFilters = new []
            {
                new FilterPath("./root-file.txt", ""),
                new FilterPath("/absolute", ""),
            }
        };

        VersionFile.SetVersion(this.RepoPath, rootVersionOptions);

        var versionOptions = new VersionOptions
        {
            Version = SemanticVersion.Parse("1.2"),
            Inherit = true
        };
        var projectDirectory = Path.Combine(this.RepoPath, "quux");

        VersionFile.SetVersion(projectDirectory, versionOptions);

        var expected = rootVersionOptions.PathFilters.Select(x => x.RepoRelativePath).ToList();

        var actualVersionOptions = VersionFile.GetVersion(projectDirectory);
        var actual = actualVersionOptions.PathFilters.Select(x => x.RepoRelativePath).ToList();

        Assert.Equal(expected, actual);
    }
    public void GetVersion_ThrowsWithPathFiltersOutsideOfGitRepo()
    {
        var json = @"{ ""version"" : ""1.2"", ""pathFilters"" : [ ""."" ] }";
        var path = Path.Combine(this.RepoPath, "version.json");

        File.WriteAllText(path, json);

        Assert.Throws <ArgumentNullException>(() => VersionFile.GetVersion(this.RepoPath));
    }
    public void GetVersion_CanReadSpecConformantJsonFile()
    {
        File.WriteAllText(Path.Combine(this.RepoPath, VersionFile.JsonFileName), "{ version: \"1.2-pre\" }");
        VersionOptions actualVersion = VersionFile.GetVersion(this.RepoPath);

        Assert.NotNull(actualVersion);
        Assert.Equal(new Version(1, 2), actualVersion.Version.Version);
        Assert.Equal("-pre", actualVersion.Version.Prerelease);
    }
    public void GetVersion_CanReadSpecConformantTxtFile_MultiLineNoHyphen()
    {
        File.WriteAllText(Path.Combine(this.RepoPath, VersionFile.TxtFileName), "1.2\npre");
        VersionOptions actualVersion = VersionFile.GetVersion(this.RepoPath);

        Assert.NotNull(actualVersion);
        Assert.Equal(new Version(1, 2), actualVersion.Version.Version);
        Assert.Equal("-pre", actualVersion.Version.Prerelease);
    }
    public void PrepareRelease_ReleaseBranch(string initialVersion, string releaseOptionsBranchName, string releaseUnstableTag, string releaseBranchName, string resultingVersion)
    {
        releaseOptionsBranchName = releaseOptionsBranchName ?? new ReleaseOptions().BranchNameOrDefault;

        // create and configure repository
        this.InitializeSourceControl();
        this.Repo.Config.Set("user.name", this.Signer.Name, ConfigurationLevel.Local);
        this.Repo.Config.Set("user.email", this.Signer.Email, ConfigurationLevel.Local);

        var initialVersionOptions = new VersionOptions()
        {
            Version = SemanticVersion.Parse(initialVersion),
            Release = new ReleaseOptions()
            {
                BranchName = releaseOptionsBranchName
            }
        };

        var expectedVersionOptions = new VersionOptions()
        {
            Version = SemanticVersion.Parse(resultingVersion),
            Release = new ReleaseOptions()
            {
                BranchName = releaseOptionsBranchName
            }
        };

        // create version.json
        this.WriteVersionFile(initialVersionOptions);

        // switch to release branch
        var branchName = releaseBranchName;

        Commands.Checkout(this.Repo, this.Repo.CreateBranch(branchName));

        var tipBeforePrepareRelease = this.Repo.Head.Tip;

        // run PrepareRelease
        var releaseManager = new ReleaseManager();

        releaseManager.PrepareRelease(this.RepoPath, releaseUnstableTag);

        // Check if a commit was created
        {
            var updateVersionCommit = this.Repo.Head.Tip;
            Assert.NotEqual(tipBeforePrepareRelease.Id, updateVersionCommit.Id);
            Assert.Single(updateVersionCommit.Parents);
            Assert.Equal(updateVersionCommit.Parents.Single().Id, tipBeforePrepareRelease.Id);
        }

        // check version on release branch
        {
            var actualVersionOptions = VersionFile.GetVersion(this.Repo.Branches[branchName].Tip);
            Assert.Equal(expectedVersionOptions, actualVersionOptions);
        }
    }
 public void VersionJson_InheritButNoParentFileFound()
 {
     this.InitializeSourceControl();
     this.WriteVersionFile(
         new VersionOptions
     {
         Inherit = true,
         Version = SemanticVersion.Parse("14.2"),
     });
     Assert.Throws <InvalidOperationException>(() => VersionFile.GetVersion(this.Repo));
 }
    public void GetVersion_Commit()
    {
        Assert.Null(VersionFile.GetVersion((Commit)null));

        this.InitializeSourceControl();
        this.WriteVersionFile();
        VersionOptions fromCommit = VersionFile.GetVersion(this.Repo.Head.Commits.First());
        VersionOptions fromFile   = VersionFile.GetVersion(this.RepoPath);

        Assert.NotNull(fromCommit);
        Assert.Equal(fromFile, fromCommit);
    }
    public void GetVersion_ReadPathFilters()
    {
        var json = @"{ ""version"" : ""1.2"", ""pathFilters"" : [ "":/root.txt"", ""./hello"" ] }";
        var path = Path.Combine(this.RepoPath, "version.json");

        File.WriteAllText(path, json);

        var versionOptions = VersionFile.GetVersion(this.RepoPath);

        Assert.NotNull(versionOptions.PathFilters);
        Assert.Equal(new[] { ":/root.txt", "./hello" }, versionOptions.PathFilters);
    }
    private void AssertPathHasVersion(Commit commit, string absolutePath, VersionOptions expected)
    {
        var actual = VersionFile.GetVersion(absolutePath);

        Assert.Equal(expected, actual);

        // Pass in the repo-relative path to ensure the commit is used as the data source.
        string relativePath = absolutePath.Substring(this.RepoPath.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);

        actual = VersionFile.GetVersion(commit, relativePath);
        Assert.Equal(expected, actual);
    }
    public void GetVersion_ReadReleaseSettings_BranchName()
    {
        var json = @"{ ""version"" : ""1.2"", ""release"" : { ""branchName"" : ""someValue{version}""  } }";
        var path = Path.Combine(this.RepoPath, "version.json");

        File.WriteAllText(path, json);

        var versionOptions = VersionFile.GetVersion(this.RepoPath);

        Assert.NotNull(versionOptions.Release);
        Assert.NotNull(versionOptions.Release.BranchName);
        Assert.Equal("someValue{version}", versionOptions.Release.BranchName);
    }
    public void GetVersion_ReadReleaseSettings_FirstUnstableTag()
    {
        var json = @"{ ""version"" : ""1.2"", ""release"" : { ""firstUnstableTag"" : ""preview""  } }";
        var path = Path.Combine(this.RepoPath, "version.json");

        File.WriteAllText(path, json);

        var versionOptions = VersionFile.GetVersion(this.RepoPath);

        Assert.NotNull(versionOptions.Release);
        Assert.NotNull(versionOptions.Release.FirstUnstableTag);
        Assert.Equal("preview", versionOptions.Release.FirstUnstableTag);
    }
    public void GetVersion_ReadReleaseSettings_VersionIncrement()
    {
        var json = @"{ ""version"" : ""1.2"", ""release"" : { ""versionIncrement"" : ""major""  } }";
        var path = Path.Combine(this.RepoPath, "version.json");

        File.WriteAllText(path, json);

        var versionOptions = VersionFile.GetVersion(this.RepoPath);

        Assert.NotNull(versionOptions.Release);
        Assert.NotNull(versionOptions.Release.VersionIncrement);
        Assert.Equal(VersionOptions.ReleaseVersionIncrement.Major, versionOptions.Release.VersionIncrement);
    }
    public void GetVersion_JsonCompatibility(string version, string assemblyVersion, object precision, int versionHeightOffset, string[] publicReleaseRefSpec, string json)
    {
        File.WriteAllText(Path.Combine(this.RepoPath, VersionFile.JsonFileName), json);

        var options = VersionFile.GetVersion(this.RepoPath);

        Assert.NotNull(options);
        Assert.Equal(version, options.Version?.ToString());
        Assert.Equal(assemblyVersion, options.AssemblyVersion?.Version?.ToString());
        Assert.Equal(precision, options.AssemblyVersion?.PrecisionOrDefault);
        Assert.Equal(versionHeightOffset, options.VersionHeightOffsetOrDefault);
        Assert.Equal(publicReleaseRefSpec, options.PublicReleaseRefSpec);
    }
    public void SetVersion_GetVersionFromFile(string expectedVersion, string expectedPrerelease)
    {
        string pathWritten = VersionFile.SetVersion(this.RepoPath, new Version(expectedVersion), expectedPrerelease);

        Assert.Equal(Path.Combine(this.RepoPath, VersionFile.JsonFileName), pathWritten);

        string actualFileContent = File.ReadAllText(pathWritten);

        this.Logger.WriteLine(actualFileContent);

        VersionOptions actualVersion = VersionFile.GetVersion(this.RepoPath);

        Assert.Equal(new Version(expectedVersion), actualVersion.Version.Version);
        Assert.Equal(expectedPrerelease ?? string.Empty, actualVersion.Version.Prerelease);
    }
    public void GetVersion_ReadPathFilters()
    {
        this.InitializeSourceControl();

        var json = @"{ ""version"" : ""1.2"", ""pathFilters"" : [ "":/root.txt"", ""./hello"" ] }";
        var path = Path.Combine(this.RepoPath, "version.json");

        File.WriteAllText(path, json);

        var repoRelativeBaseDirectory = ".";
        var versionOptions            = VersionFile.GetVersion(this.RepoPath);

        Assert.NotNull(versionOptions.PathFilters);
        Assert.Equal(new[] { "/root.txt", "./hello" }, versionOptions.PathFilters.Select(fp => fp.ToPathSpec(repoRelativeBaseDirectory)));
    }
Esempio n. 17
0
        private static ExitCodes OnSetVersionCommand(string projectPath, string version)
        {
            if (!SemanticVersion.TryParse(string.IsNullOrEmpty(version) ? DefaultVersionSpec : version, out var semver))
            {
                Console.Error.WriteLine($"\"{version}\" is not a semver-compliant version spec.");
                return(ExitCodes.InvalidVersionSpec);
            }

            var defaultOptions = new VersionOptions
            {
                Version = semver,
            };

            string searchPath      = GetSpecifiedOrCurrentDirectoryPath(projectPath);
            var    repository      = GitExtensions.OpenGitRepo(searchPath);
            var    existingOptions = VersionFile.GetVersion(searchPath, out string actualDirectory);
            string versionJsonPath;

            if (existingOptions != null)
            {
                existingOptions.Version = semver;
                versionJsonPath         = VersionFile.SetVersion(actualDirectory, existingOptions);
            }
            else if (string.IsNullOrEmpty(projectPath))
            {
                if (repository == null)
                {
                    Console.Error.WriteLine("No version file and no git repo found at or above: \"{0}\"", searchPath);
                    return(ExitCodes.NoGitRepo);
                }

                versionJsonPath = VersionFile.SetVersion(repository.Info.WorkingDirectory, defaultOptions);
            }
            else
            {
                versionJsonPath = VersionFile.SetVersion(projectPath, defaultOptions);
            }

            if (repository != null)
            {
                LibGit2Sharp.Commands.Stage(repository, versionJsonPath);
            }

            return(ExitCodes.OK);
        }
    public void SetVersion_GetVersionFromFile(string expectedVersion, string expectedPrerelease)
    {
        string pathWritten = VersionFile.SetVersion(this.RepoPath, new Version(expectedVersion), expectedPrerelease);

        Assert.Equal(Path.Combine(this.RepoPath, VersionFile.FileName), pathWritten);

        string[] actualFileContent = File.ReadAllLines(this.versionTxtPath);
        this.Logger.WriteLine(string.Join(Environment.NewLine, actualFileContent));

        Assert.Equal(2, actualFileContent.Length);
        Assert.Equal(expectedVersion, actualFileContent[0]);
        Assert.Equal(expectedPrerelease ?? string.Empty, actualFileContent[1]);

        SemanticVersion actualVersion = VersionFile.GetVersion(this.RepoPath);

        Assert.Equal(new Version(expectedVersion), actualVersion.Version);
        Assert.Equal(expectedPrerelease ?? string.Empty, actualVersion.UnstableTag);
    }
Esempio n. 19
0
    public void PrepareRelease_ResetsVersionHeightOffset()
    {
        // create and configure repository
        this.InitializeSourceControl();

        var initialVersionOptions = new VersionOptions()
        {
            Version             = SemanticVersion.Parse("1.0-beta"),
            VersionHeightOffset = 5,
        };

        var expectedReleaseVersionOptions = new VersionOptions()
        {
            Version             = SemanticVersion.Parse("1.0"),
            VersionHeightOffset = 5,
        };

        var expectedMainVersionOptions = new VersionOptions()
        {
            Version = SemanticVersion.Parse("1.1-alpha"),
        };

        // create version.json
        this.WriteVersionFile(initialVersionOptions);

        var tipBeforePrepareRelease = this.Repo.Head.Tip;

        var releaseManager = new ReleaseManager();

        releaseManager.PrepareRelease(this.RepoPath);

        var newVersion = VersionFile.GetVersion(this.RepoPath);

        Assert.Equal(expectedMainVersionOptions, newVersion);

        var releaseVersion = VersionFile.GetVersion(this.Repo.Branches["v1.0"].Tip);

        Assert.Equal(expectedReleaseVersionOptions, releaseVersion);
    }
Esempio n. 20
0
    public void PrepareRelease_JsonOutput()
    {
        // create and configure repository
        this.InitializeSourceControl();

        // create version.json
        var versionOptions = new VersionOptions()
        {
            Version = SemanticVersion.Parse("1.0"),
            Release = new ReleaseOptions()
            {
                BranchName       = "v{version}",
                VersionIncrement = ReleaseVersionIncrement.Minor
            }
        };

        this.WriteVersionFile(versionOptions);

        var currentBranchName = this.Repo.Head.FriendlyName;
        var releaseBranchName = "v1.0";

        // run release preparation
        var stdout         = new StringWriter();
        var releaseManager = new ReleaseManager(stdout);

        releaseManager.PrepareRelease(this.RepoPath, outputMode: ReleaseManager.ReleaseManagerOutputMode.Json);


        // Expected output:
        // {
        //     "CurrentBranch" : {
        //         "Name" : "<NAME-OF-CURRENT-BRANCH>",
        //         "Commit" : "<HEAD-COMMIT-OF-CURRENT-BRANCH>",
        //         "Version" : "<UPDATED-VERSION-ON-CURRENT-BRANCH>",
        //     },
        //     "NewBranch" : {
        //         "Name" : "<NAME-OF-CREATED-BRANCH>",
        //         "Commit" : "<HEAD-COMMIT-OF-CREATED-BRANCH>",
        //         "Version" : "<VERSION-ON-CREATED-BRANCH>",
        //     }
        // }

        var jsonOutput = JObject.Parse(stdout.ToString());

        // check "CurrentBranch" output
        {
            var expectedCommitId = this.Repo.Branches[currentBranchName].Tip.Sha;
            var expectedVersion  = VersionFile.GetVersion(this.Repo.Branches[currentBranchName].Tip).Version.ToString();

            var currentBranchOutput = jsonOutput.Property("CurrentBranch")?.Value as JObject;
            Assert.NotNull(currentBranchOutput);

            Assert.Equal(currentBranchName, currentBranchOutput.GetValue("Name")?.ToString());
            Assert.Equal(expectedCommitId, currentBranchOutput.GetValue("Commit")?.ToString());
            Assert.Equal(expectedVersion, currentBranchOutput.GetValue("Version")?.ToString());
        }

        // Check "NewBranch" output
        {
            var expectedCommitId = this.Repo.Branches[releaseBranchName].Tip.Sha;
            var expectedVersion  = VersionFile.GetVersion(this.Repo.Branches[releaseBranchName].Tip).Version.ToString();

            var newBranchOutput = jsonOutput.Property("NewBranch")?.Value as JObject;
            Assert.NotNull(newBranchOutput);

            Assert.Equal(releaseBranchName, newBranchOutput.GetValue("Name")?.ToString());
            Assert.Equal(expectedCommitId, newBranchOutput.GetValue("Commit")?.ToString());
            Assert.Equal(expectedVersion, newBranchOutput.GetValue("Version")?.ToString());
        }
    }
    public void PrepareRelease_Master(
        // data for initial setup (version and release options configured in version.json)
        string initialVersion,
        string releaseOptionsBranchName,
        ReleaseVersionIncrement?releaseOptionsVersionIncrement,
        string releaseOptionsFirstUnstableTag,
        // arguments passed to PrepareRelease()
        string releaseUnstableTag,
        string nextVersion,
        ReleaseVersionIncrement?parameterVersionIncrement,
        // expected versions and branch name after running PrepareRelease()
        string expectedBranchName,
        string resultingReleaseVersion,
        string resultingMainVersion)
    {
        // create and configure repository
        this.InitializeSourceControl();
        this.Repo.Config.Set("user.name", this.Signer.Name, ConfigurationLevel.Local);
        this.Repo.Config.Set("user.email", this.Signer.Email, ConfigurationLevel.Local);

        // create version.json
        var initialVersionOptions = new VersionOptions()
        {
            Version = SemanticVersion.Parse(initialVersion),
            Release = new ReleaseOptions()
            {
                VersionIncrement = releaseOptionsVersionIncrement,
                BranchName       = releaseOptionsBranchName,
                FirstUnstableTag = releaseOptionsFirstUnstableTag
            }
        };

        this.WriteVersionFile(initialVersionOptions);

        var expectedVersionOptionsReleaseBranch = new VersionOptions()
        {
            Version = SemanticVersion.Parse(resultingReleaseVersion),
            Release = new ReleaseOptions()
            {
                VersionIncrement = releaseOptionsVersionIncrement,
                BranchName       = releaseOptionsBranchName,
                FirstUnstableTag = releaseOptionsFirstUnstableTag
            }
        };

        var expectedVersionOptionsCurrentBrach = new VersionOptions()
        {
            Version = SemanticVersion.Parse(resultingMainVersion),
            Release = new ReleaseOptions()
            {
                VersionIncrement = releaseOptionsVersionIncrement,
                BranchName       = releaseOptionsBranchName,
                FirstUnstableTag = releaseOptionsFirstUnstableTag
            }
        };

        var initialBranchName       = this.Repo.Head.FriendlyName;
        var tipBeforePrepareRelease = this.Repo.Head.Tip;

        // prepare release
        var releaseManager = new ReleaseManager();

        releaseManager.PrepareRelease(this.RepoPath, releaseUnstableTag, (nextVersion == null ? null : Version.Parse(nextVersion)), parameterVersionIncrement);

        // check if a branch was created
        Assert.Contains(this.Repo.Branches, branch => branch.FriendlyName == expectedBranchName);

        // PrepareRelease should switch back to the initial branch
        Assert.Equal(initialBranchName, this.Repo.Head.FriendlyName);

        // check if release branch contains a new commit
        // parent of new commit must be the commit before preparing the release
        var releaseBranch = this.Repo.Branches[expectedBranchName];

        {
            // If the original branch had no -prerelease tag, the release branch has no commit to author.
            if (string.IsNullOrEmpty(initialVersionOptions.Version.Prerelease))
            {
                Assert.Equal(releaseBranch.Tip.Id, tipBeforePrepareRelease.Id);
            }
            else
            {
                Assert.NotEqual(releaseBranch.Tip.Id, tipBeforePrepareRelease.Id);
                Assert.Equal(releaseBranch.Tip.Parents.Single().Id, tipBeforePrepareRelease.Id);
            }
        }

        if (string.IsNullOrEmpty(initialVersionOptions.Version.Prerelease))
        {
            // Verify that one commit was authored.
            var incrementCommit = this.Repo.Head.Tip;
            Assert.Single(incrementCommit.Parents);
            Assert.Equal(tipBeforePrepareRelease.Id, incrementCommit.Parents.Single().Id);
        }
        else
        {
            // check if current branch contains new commits
            // - one commit that updates the version (parent must be the commit before preparing the release)
            // - one commit merging the release branch back to master and resolving the conflict
            var mergeCommit = this.Repo.Head.Tip;
            Assert.Equal(2, mergeCommit.Parents.Count());
            Assert.Equal(releaseBranch.Tip.Id, mergeCommit.Parents.Skip(1).First().Id);

            var updateVersionCommit = mergeCommit.Parents.First();
            Assert.Single(updateVersionCommit.Parents);
            Assert.Equal(tipBeforePrepareRelease.Id, updateVersionCommit.Parents.First().Id);
        }

        // check version on release branch
        {
            var releaseBranchVersion = VersionFile.GetVersion(releaseBranch.Tip);
            Assert.Equal(expectedVersionOptionsReleaseBranch, releaseBranchVersion);
        }

        // check version on master branch
        {
            var currentBranchVersion = VersionFile.GetVersion(this.Repo.Head.Tip);
            Assert.Equal(expectedVersionOptionsCurrentBrach, currentBranchVersion);
        }
    }
Esempio n. 22
0
        private static ExitCodes OnInstallCommand(string versionJsonRoot, string version, IReadOnlyList <string> sources)
        {
            if (!SemanticVersion.TryParse(string.IsNullOrEmpty(version) ? DefaultVersionSpec : version, out var semver))
            {
                Console.Error.WriteLine($"\"{version}\" is not a semver-compliant version spec.");
                return(ExitCodes.InvalidVersionSpec);
            }

            var options = new VersionOptions
            {
                Version = semver,
                PublicReleaseRefSpec = new string[]
                {
                    @"^refs/heads/master$",
                    @"^refs/heads/v\d+(?:\.\d+)?$",
                },
                CloudBuild = new VersionOptions.CloudBuildOptions
                {
                    BuildNumber = new VersionOptions.CloudBuildNumberOptions
                    {
                        Enabled = true,
                    },
                },
            };
            string searchPath = GetSpecifiedOrCurrentDirectoryPath(versionJsonRoot);

            if (!Directory.Exists(searchPath))
            {
                Console.Error.WriteLine("\"{0}\" is not an existing directory.", searchPath);
                return(ExitCodes.NoGitRepo);
            }

            var repository = GitExtensions.OpenGitRepo(searchPath);

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

            if (string.IsNullOrEmpty(versionJsonRoot))
            {
                versionJsonRoot = repository.Info.WorkingDirectory;
            }

            var existingOptions = VersionFile.GetVersion(versionJsonRoot);

            if (existingOptions != null)
            {
                if (!string.IsNullOrEmpty(version))
                {
                    var setVersionExitCode = OnSetVersionCommand(versionJsonRoot, version);
                    if (setVersionExitCode != ExitCodes.OK)
                    {
                        return(setVersionExitCode);
                    }
                }
            }
            else
            {
                string versionJsonPath = VersionFile.SetVersion(versionJsonRoot, options);
                LibGit2Sharp.Commands.Stage(repository, versionJsonPath);
            }

            // Create/update the Directory.Build.props file in the directory of the version.json file to add the NB.GV package.
            string directoryBuildPropsPath = Path.Combine(versionJsonRoot, "Directory.Build.props");

            MSBuild.Project propsFile;
            if (File.Exists(directoryBuildPropsPath))
            {
                propsFile = new MSBuild.Project(directoryBuildPropsPath);
            }
            else
            {
                propsFile = new MSBuild.Project();
            }

            const string PackageReferenceItemType = "PackageReference";

            if (!propsFile.GetItemsByEvaluatedInclude(PackageId).Any(i => i.ItemType == "PackageReference"))
            {
                // Validate given sources
                foreach (var source in sources)
                {
                    if (!Uri.TryCreate(source, UriKind.Absolute, out var _))
                    {
                        Console.Error.WriteLine($"\"{source}\" is not a valid NuGet package source.");
                        return(ExitCodes.InvalidNuGetPackageSource);
                    }
                }

                string packageVersion = GetLatestPackageVersionAsync(PackageId, versionJsonRoot, sources).GetAwaiter().GetResult();
                if (string.IsNullOrEmpty(packageVersion))
                {
                    string verifyPhrase = sources.Any()
                        ? "Please verify the given 'source' option(s)."
                        : "Please verify the package sources in the NuGet.Config files.";
                    Console.Error.WriteLine($"Latest stable version of the {PackageId} package could not be determined. " + verifyPhrase);
                    return(ExitCodes.PackageIdNotFound);
                }

                propsFile.AddItem(
                    PackageReferenceItemType,
                    PackageId,
                    new Dictionary <string, string>
                {
                    { "Version", packageVersion },
                    { "PrivateAssets", "all" },
                });

                propsFile.Save(directoryBuildPropsPath);
            }

            LibGit2Sharp.Commands.Stage(repository, directoryBuildPropsPath);

            return(ExitCodes.OK);
        }
        public override bool Execute()
        {
            try
            {
                Version        typedVersion;
                VersionOptions versionOptions;
                using (var git = this.OpenGitRepo())
                {
                    var repoRoot = git?.Info?.WorkingDirectory?.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
                    var relativeRepoProjectDirectory = !string.IsNullOrWhiteSpace(repoRoot)
                        ? Environment.CurrentDirectory.Substring(repoRoot.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
                        : null;

                    var commit = git?.Head.Commits.FirstOrDefault();
                    this.GitCommitId      = commit?.Id.Sha ?? string.Empty;
                    this.GitVersionHeight = git?.GetVersionHeight(relativeRepoProjectDirectory) ?? 0;
                    if (string.IsNullOrEmpty(this.BuildingRef))
                    {
                        this.BuildingRef = git?.Head.CanonicalName;
                    }

                    versionOptions =
                        VersionFile.GetVersion(git, Environment.CurrentDirectory) ??
                        VersionFile.GetVersion(Environment.CurrentDirectory);

                    this.PublicRelease = string.Equals(this.DefaultPublicRelease, "true", StringComparison.OrdinalIgnoreCase);
                    if (string.IsNullOrEmpty(this.DefaultPublicRelease))
                    {
                        if (!string.IsNullOrEmpty(this.BuildingRef) && versionOptions?.PublicReleaseRefSpec?.Length > 0)
                        {
                            this.PublicRelease = versionOptions.PublicReleaseRefSpec.Any(
                                expr => Regex.IsMatch(this.BuildingRef, expr));
                        }
                    }

                    this.PrereleaseVersion = versionOptions?.Version.Prerelease ?? string.Empty;

                    // Override the typedVersion with the special build number and revision components, when available.
                    typedVersion = git?.GetIdAsVersion(relativeRepoProjectDirectory, this.GitVersionHeight) ?? versionOptions?.Version.Version;
                }

                typedVersion = typedVersion ?? new Version();
                var typedVersionWithoutRevision = typedVersion.Build >= 0
                    ? new Version(typedVersion.Major, typedVersion.Minor, typedVersion.Build)
                    : new Version(typedVersion.Major, typedVersion.Minor);
                this.SimpleVersion = typedVersionWithoutRevision.ToString();
                var majorMinorVersion = new Version(typedVersion.Major, typedVersion.Minor);
                this.MajorMinorVersion = majorMinorVersion.ToString();
                Version assemblyVersion = GetAssemblyVersion(typedVersion, versionOptions);
                this.AssemblyVersion = assemblyVersion.ToStringSafe(4);
                this.BuildNumber     = Math.Max(0, typedVersion.Build);
                this.Version         = typedVersion.ToString();

                this.SetCloudBuildVersionVars = versionOptions?.CloudBuild?.SetVersionVariables
                                                ?? (new VersionOptions.CloudBuildOptions()).SetVersionVariables;

                var buildMetadata = this.BuildMetadata?.ToList() ?? new List <string>();
                if (!string.IsNullOrEmpty(this.GitCommitId))
                {
                    buildMetadata.Insert(0, $"g{this.GitCommitId.Substring(0, 10)}");
                }

                this.BuildMetadataFragment = FormatBuildMetadata(buildMetadata);

                var buildNumber = versionOptions?.CloudBuild?.BuildNumber ?? new VersionOptions.CloudBuildNumberOptions();
                if (buildNumber.Enabled)
                {
                    var  commitIdOptions   = buildNumber.IncludeCommitId ?? new VersionOptions.CloudBuildNumberCommitIdOptions();
                    bool includeCommitInfo = commitIdOptions.When == VersionOptions.CloudBuildNumberCommitWhen.Always ||
                                             (commitIdOptions.When == VersionOptions.CloudBuildNumberCommitWhen.NonPublicReleaseOnly && !this.PublicRelease);
                    bool    commitIdInRevision      = includeCommitInfo && commitIdOptions.Where == VersionOptions.CloudBuildNumberCommitWhere.FourthVersionComponent;
                    bool    commitIdInBuildMetadata = includeCommitInfo && commitIdOptions.Where == VersionOptions.CloudBuildNumberCommitWhere.BuildMetadata;
                    Version buildNumberVersion      = commitIdInRevision ? typedVersion : typedVersionWithoutRevision;
                    string  buildNumberMetadata     = FormatBuildMetadata(commitIdInBuildMetadata ? (IEnumerable <string>)buildMetadata : this.BuildMetadata);
                    this.CloudBuildNumber = buildNumberVersion + this.PrereleaseVersion + buildNumberMetadata;
                }
            }
            catch (ArgumentOutOfRangeException ex)
            {
                Log.LogErrorFromException(ex);
                return(false);
            }

            return(true);
        }
    public void VersionJson_Inheritance(bool commitInSourceControl, bool bareRepo)
    {
        if (commitInSourceControl)
        {
            this.InitializeSourceControl();
        }

        VersionOptions level1, level2, level3, level2NoInherit, level2InheritButResetVersion;

        this.WriteVersionFile(
            level1 = new VersionOptions
        {
            Version         = SemanticVersion.Parse("14.2"),
            AssemblyVersion = new VersionOptions.AssemblyVersionOptions {
                Precision = VersionOptions.VersionPrecision.Major
            },
        });
        this.WriteVersionFile(
            level2 = new VersionOptions
        {
            Inherit         = true,
            AssemblyVersion = new VersionOptions.AssemblyVersionOptions {
                Precision = VersionOptions.VersionPrecision.Minor
            },
        },
            "foo");
        this.WriteVersionFile(
            level3 = new VersionOptions
        {
            Inherit             = true,
            VersionHeightOffset = 1,
        },
            @"foo\bar");
        this.WriteVersionFile(
            level2NoInherit = new VersionOptions
        {
            Version = SemanticVersion.Parse("10.1"),
        },
            @"noInherit");
        this.WriteVersionFile(
            level2InheritButResetVersion = new VersionOptions
        {
            Inherit = true,
            Version = SemanticVersion.Parse("8.2"),
        },
            @"inheritWithVersion");

        Repository operatingRepo = this.Repo;

        if (bareRepo)
        {
            operatingRepo = new Repository(
                Repository.Clone(this.RepoPath, this.CreateDirectoryForNewRepo(), new CloneOptions {
                IsBare = true
            }));
        }

        using (operatingRepo)
        {
            VersionOptions GetOption(string path) => commitInSourceControl?VersionFile.GetVersion(operatingRepo, path) : VersionFile.GetVersion(Path.Combine(this.RepoPath, path));

            var level1Options = GetOption(string.Empty);
            Assert.False(level1Options.Inherit);

            var level2Options = GetOption("foo");
            Assert.Equal(level1.Version.Version.Major, level2Options.Version.Version.Major);
            Assert.Equal(level1.Version.Version.Minor, level2Options.Version.Version.Minor);
            Assert.Equal(level2.AssemblyVersion.Precision, level2Options.AssemblyVersion.Precision);
            Assert.True(level2Options.Inherit);

            var level3Options = GetOption(@"foo\bar");
            Assert.Equal(level1.Version.Version.Major, level3Options.Version.Version.Major);
            Assert.Equal(level1.Version.Version.Minor, level3Options.Version.Version.Minor);
            Assert.Equal(level2.AssemblyVersion.Precision, level3Options.AssemblyVersion.Precision);
            Assert.Equal(level2.AssemblyVersion.Precision, level3Options.AssemblyVersion.Precision);
            Assert.Equal(level3.VersionHeightOffset, level3Options.VersionHeightOffset);
            Assert.True(level3Options.Inherit);

            var level2NoInheritOptions = GetOption("noInherit");
            Assert.Equal(level2NoInherit.Version, level2NoInheritOptions.Version);
            Assert.Equal(VersionOptions.DefaultVersionPrecision, level2NoInheritOptions.AssemblyVersionOrDefault.PrecisionOrDefault);
            Assert.False(level2NoInheritOptions.Inherit);

            var level2InheritButResetVersionOptions = GetOption("inheritWithVersion");
            Assert.Equal(level2InheritButResetVersion.Version, level2InheritButResetVersionOptions.Version);
            Assert.True(level2InheritButResetVersionOptions.Inherit);

            if (commitInSourceControl)
            {
                int totalCommits = operatingRepo.Head.Commits.Count();

                // The version height should be the same for all those that inherit the version from the base,
                // even though the inheriting files were introduced in successive commits.
                Assert.Equal(totalCommits, operatingRepo.GetVersionHeight());
                Assert.Equal(totalCommits, operatingRepo.GetVersionHeight("foo"));
                Assert.Equal(totalCommits, operatingRepo.GetVersionHeight(@"foo\bar"));

                // These either don't inherit, or inherit but reset versions, so the commits were reset.
                Assert.Equal(2, operatingRepo.GetVersionHeight("noInherit"));
                Assert.Equal(1, operatingRepo.GetVersionHeight("inheritWithVersion"));
            }
        }
    }
Esempio n. 25
0
        private static ExitCodes OnInstallCommand(string versionJsonRoot, string version)
        {
            if (!SemanticVersion.TryParse(string.IsNullOrEmpty(version) ? DefaultVersionSpec : version, out var semver))
            {
                Console.Error.WriteLine($"\"{version}\" is not a semver-compliant version spec.");
                return(ExitCodes.InvalidVersionSpec);
            }

            var options = new VersionOptions
            {
                Version = semver,
                PublicReleaseRefSpec = new string[]
                {
                    @"^refs/heads/master$",
                    @"^refs/heads/v\d+(?:\.\d+)?$",
                },
                CloudBuild = new VersionOptions.CloudBuildOptions
                {
                    BuildNumber = new VersionOptions.CloudBuildNumberOptions
                    {
                        Enabled = true,
                    },
                },
            };
            string searchPath = GetSpecifiedOrCurrentDirectoryPath(versionJsonRoot);

            if (!Directory.Exists(searchPath))
            {
                Console.Error.WriteLine("\"{0}\" is not an existing directory.", searchPath);
                return(ExitCodes.NoGitRepo);
            }

            var repository = GitExtensions.OpenGitRepo(searchPath);

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

            if (string.IsNullOrEmpty(versionJsonRoot))
            {
                versionJsonRoot = repository.Info.WorkingDirectory;
            }

            var existingOptions = VersionFile.GetVersion(versionJsonRoot);

            if (existingOptions != null)
            {
                if (!string.IsNullOrEmpty(version))
                {
                    var setVersionExitCode = OnSetVersionCommand(versionJsonRoot, version);
                    if (setVersionExitCode != ExitCodes.OK)
                    {
                        return(setVersionExitCode);
                    }
                }
            }
            else
            {
                string versionJsonPath = VersionFile.SetVersion(versionJsonRoot, options);
                LibGit2Sharp.Commands.Stage(repository, versionJsonPath);
            }

            // Create/update the Directory.Build.props file in the directory of the version.json file to add the NB.GV package.
            string directoryBuildPropsPath = Path.Combine(versionJsonRoot, "Directory.Build.props");

            MSBuild.Project propsFile;
            if (File.Exists(directoryBuildPropsPath))
            {
                propsFile = new MSBuild.Project(directoryBuildPropsPath);
            }
            else
            {
                propsFile = new MSBuild.Project();
            }

            const string PackageReferenceItemType = "PackageReference";
            const string PackageId = "Nerdbank.GitVersioning";

            if (!propsFile.GetItemsByEvaluatedInclude(PackageId).Any(i => i.ItemType == "PackageReference"))
            {
                string packageVersion = GetLatestPackageVersionAsync(PackageId).GetAwaiter().GetResult();
                propsFile.AddItem(
                    PackageReferenceItemType,
                    PackageId,
                    new Dictionary <string, string>
                {
                    { "Version", packageVersion },     // TODO: use the latest version... somehow...
                    { "PrivateAssets", "all" },
                });

                propsFile.Save(directoryBuildPropsPath);
            }

            LibGit2Sharp.Commands.Stage(repository, directoryBuildPropsPath);

            return(ExitCodes.OK);
        }
 public void GetVersion_String_MissingFile()
 {
     Assert.Null(VersionFile.GetVersion(this.RepoPath));
 }