/// <summary>
        /// Writes the version.json file to a directory within a repo with the specified version information.
        /// </summary>
        /// <param name="projectDirectory">
        /// The path to the directory in which to write the version.json file.
        /// The file's impact will be all descendent projects and directories from this specified directory,
        /// except where any of those directories have their own version.json file.
        /// </param>
        /// <param name="version">The version information to write to the file.</param>
        /// <returns>The path to the file written.</returns>
        public static string SetVersion(string projectDirectory, VersionOptions version)
        {
            Requires.NotNullOrEmpty(projectDirectory, nameof(projectDirectory));
            Requires.NotNull(version, nameof(version));
            Requires.Argument(version.Version != null || version.Inherit, nameof(version), $"{nameof(VersionOptions.Version)} must be set for a root-level version.json file.");

            Directory.CreateDirectory(projectDirectory);

            string versionTxtPath = Path.Combine(projectDirectory, TxtFileName);

            if (File.Exists(versionTxtPath))
            {
                if (version.IsDefaultVersionTheOnlyPropertySet)
                {
                    File.WriteAllLines(
                        versionTxtPath,
                        new[] { version.Version.Version.ToString(), version.Version.Prerelease });
                    return(versionTxtPath);
                }
                else
                {
                    // The file must be upgraded to use the more descriptive JSON format.
                    File.Delete(versionTxtPath);
                }
            }

            string versionJsonPath = Path.Combine(projectDirectory, JsonFileName);
            var    jsonContent     = JsonConvert.SerializeObject(version, VersionOptions.GetJsonSettings(version.Inherit));

            File.WriteAllText(versionJsonPath, jsonContent);
            return(versionJsonPath);
        }
 /// <summary>
 /// Tries to read a version.json file from the specified string, but favors returning null instead of throwing a <see cref="JsonSerializationException"/>.
 /// </summary>
 /// <param name="jsonContent">The content of the version.json file.</param>
 /// <returns>The deserialized <see cref="VersionOptions"/> object, if deserialization was successful.</returns>
 private static VersionOptions TryReadVersionJsonContent(string jsonContent)
 {
     try
     {
         return(JsonConvert.DeserializeObject <VersionOptions>(jsonContent, VersionOptions.GetJsonSettings()));
     }
     catch (JsonSerializationException)
     {
         return(null);
     }
 }
 /// <summary>
 /// Tries to read a version.json file from the specified string, but favors returning null instead of throwing a <see cref="JsonSerializationException"/>.
 /// </summary>
 /// <param name="jsonContent">The content of the version.json file.</param>
 /// <param name="repoRelativeBaseDirectory">Directory that this version.json file is relative to the root of the repository.</param>
 /// <returns>The deserialized <see cref="VersionOptions"/> object, if deserialization was successful.</returns>
 private static VersionOptions TryReadVersionJsonContent(string jsonContent, string repoRelativeBaseDirectory)
 {
     try
     {
         return(JsonConvert.DeserializeObject <VersionOptions>(jsonContent, VersionOptions.GetJsonSettings(repoRelativeBaseDirectory: repoRelativeBaseDirectory)));
     }
     catch (JsonSerializationException)
     {
         return(null);
     }
 }
        /// <summary>
        /// Reads the version.txt file and returns the <see cref="Version"/> and prerelease tag from it.
        /// </summary>
        /// <param name="commit">The commit to read the version file from.</param>
        /// <param name="repoRelativeProjectDirectory">The directory to consider when searching for the version.txt file.</param>
        /// <returns>The version information read from the file.</returns>
        public static VersionOptions GetVersion(LibGit2Sharp.Commit commit, string repoRelativeProjectDirectory = null)
        {
            if (commit == null)
            {
                return(null);
            }

            string searchDirectory = repoRelativeProjectDirectory ?? string.Empty;

            while (searchDirectory != null)
            {
                string parentDirectory = searchDirectory.Length > 0 ? Path.GetDirectoryName(searchDirectory) : null;

                string candidatePath  = Path.Combine(searchDirectory, TxtFileName).Replace('\\', '/');
                var    versionTxtBlob = commit.Tree[candidatePath]?.Target as LibGit2Sharp.Blob;
                if (versionTxtBlob != null)
                {
                    var result = TryReadVersionFile(new StreamReader(versionTxtBlob.GetContentStream()), isJsonFile: false);
                    if (result != null)
                    {
                        return(result);
                    }
                }

                candidatePath = Path.Combine(searchDirectory, JsonFileName).Replace('\\', '/');
                var versionJsonBlob = commit.Tree[candidatePath]?.Target as LibGit2Sharp.Blob;
                if (versionJsonBlob != null)
                {
                    string versionJsonContent;
                    using (var sr = new StreamReader(versionJsonBlob.GetContentStream()))
                    {
                        versionJsonContent = sr.ReadToEnd();
                    }

                    VersionOptions result;
                    try
                    {
                        result = TryReadVersionJsonContent(versionJsonContent);
                    }
                    catch (FormatException ex)
                    {
                        throw new FormatException(
                                  $"Failure while reading {JsonFileName} from commit {commit.Sha}. " +
                                  "Fix this commit with rebase if this is an error, or review this doc on how to migrate to Nerdbank.GitVersioning: " +
                                  "https://github.com/AArnott/Nerdbank.GitVersioning/blob/master/doc/migrating.md", ex);
                    }

                    if (result?.Inherit ?? false)
                    {
                        if (parentDirectory != null)
                        {
                            result = GetVersion(commit, parentDirectory);
                            if (result != null)
                            {
                                JsonConvert.PopulateObject(versionJsonContent, result, VersionOptions.GetJsonSettings());
                                return(result);
                            }
                        }

                        throw new InvalidOperationException($"\"{candidatePath}\" inherits from a parent directory version.json file but none exists.");
                    }
                    else if (result != null)
                    {
                        return(result);
                    }
                }

                searchDirectory = parentDirectory;
            }

            return(null);
        }
        /// <summary>
        /// Reads the version.txt file and returns the <see cref="Version"/> and prerelease tag from it.
        /// </summary>
        /// <param name="projectDirectory">The path to the directory which may (or its ancestors may) define the version.txt file.</param>
        /// <param name="actualDirectory">Set to the actual directory that the version file was found in, which may be <paramref name="projectDirectory"/> or one of its ancestors.</param>
        /// <returns>The version information read from the file, or <c>null</c> if the file wasn't found.</returns>
        public static VersionOptions GetVersion(string projectDirectory, out string actualDirectory)
        {
            Requires.NotNullOrEmpty(projectDirectory, nameof(projectDirectory));

            string searchDirectory = projectDirectory;

            while (searchDirectory != null)
            {
                string parentDirectory = Path.GetDirectoryName(searchDirectory);
                string versionTxtPath  = Path.Combine(searchDirectory, TxtFileName);
                if (File.Exists(versionTxtPath))
                {
                    using (var sr = new StreamReader(File.OpenRead(versionTxtPath)))
                    {
                        var result = TryReadVersionFile(sr, isJsonFile: false);
                        if (result != null)
                        {
                            actualDirectory = searchDirectory;
                            return(result);
                        }
                    }
                }

                string versionJsonPath = Path.Combine(searchDirectory, JsonFileName);
                if (File.Exists(versionJsonPath))
                {
                    string         versionJsonContent = File.ReadAllText(versionJsonPath);
                    VersionOptions result             = TryReadVersionJsonContent(versionJsonContent);
                    if (result?.Inherit ?? false)
                    {
                        if (parentDirectory != null)
                        {
                            result = GetVersion(parentDirectory);
                            if (result != null)
                            {
                                JsonConvert.PopulateObject(versionJsonContent, result, VersionOptions.GetJsonSettings());
                                actualDirectory = searchDirectory;
                                return(result);
                            }
                        }

                        throw new InvalidOperationException($"\"{versionJsonPath}\" inherits from a parent directory version.json file but none exists.");
                    }
                    else if (result != null)
                    {
                        actualDirectory = searchDirectory;
                        return(result);
                    }
                }

                searchDirectory = parentDirectory;
            }

            actualDirectory = null;
            return(null);
        }
Exemple #6
0
        /// <summary>
        /// Reads the version.txt file and returns the <see cref="Version"/> and prerelease tag from it.
        /// </summary>
        /// <param name="commit">The commit to read the version file from.</param>
        /// <param name="repoRelativeProjectDirectory">The directory to consider when searching for the version.txt file.</param>
        /// <returns>The version information read from the file.</returns>
        public static VersionOptions GetVersion(LibGit2Sharp.Commit commit, string repoRelativeProjectDirectory = null)
        {
            if (commit == null)
            {
                return(null);
            }

            string searchDirectory = repoRelativeProjectDirectory ?? string.Empty;

            while (searchDirectory != null)
            {
                string parentDirectory = searchDirectory.Length > 0 ? Path.GetDirectoryName(searchDirectory) : null;

                string candidatePath  = Path.Combine(searchDirectory, TxtFileName).Replace('\\', '/');
                var    versionTxtBlob = commit.Tree[candidatePath]?.Target as LibGit2Sharp.Blob;
                if (versionTxtBlob != null)
                {
                    var result = TryReadVersionFile(new StreamReader(versionTxtBlob.GetContentStream()), isJsonFile: false);
                    if (result != null)
                    {
                        return(result);
                    }
                }

                candidatePath = Path.Combine(searchDirectory, JsonFileName).Replace('\\', '/');
                var versionJsonBlob = commit.Tree[candidatePath]?.Target as LibGit2Sharp.Blob;
                if (versionJsonBlob != null)
                {
                    string versionJsonContent;
                    using (var sr = new StreamReader(versionJsonBlob.GetContentStream()))
                    {
                        versionJsonContent = sr.ReadToEnd();
                    }

                    VersionOptions result = TryReadVersionJsonContent(versionJsonContent);
                    if (result?.Inherit ?? false)
                    {
                        if (parentDirectory != null)
                        {
                            result = GetVersion(commit, parentDirectory);
                            if (result != null)
                            {
                                JsonConvert.PopulateObject(versionJsonContent, result, VersionOptions.GetJsonSettings());
                                return(result);
                            }
                        }

                        throw new InvalidOperationException($"\"{candidatePath}\" inherits from a parent directory version.json file but none exists.");
                    }
                    else if (result != null)
                    {
                        return(result);
                    }
                }

                searchDirectory = parentDirectory;
            }

            return(null);
        }
        /// <summary>
        /// Reads the version.json file and returns the <see cref="Version"/> and prerelease tag from it.
        /// </summary>
        /// <param name="commit">The commit to read the version file from.</param>
        /// <param name="repoRelativeProjectDirectory">The directory to consider when searching for the version.txt file.</param>
        /// <param name="blobVersionCache">An optional blob cache for storing the raw parse results of a version.txt or version.json file (before any inherit merge operations are applied).</param>
        /// <returns>The version information read from the file.</returns>
        public static VersionOptions GetVersion(LibGit2Sharp.Commit commit, string repoRelativeProjectDirectory = null, Dictionary <LibGit2Sharp.ObjectId, VersionOptions> blobVersionCache = null)
        {
            if (commit == null)
            {
                return(null);
            }

            string searchDirectory = repoRelativeProjectDirectory ?? string.Empty;

            while (searchDirectory != null)
            {
                string parentDirectory = searchDirectory.Length > 0 ? Path.GetDirectoryName(searchDirectory) : null;

                string candidatePath  = Path.Combine(searchDirectory, TxtFileName).Replace('\\', '/');
                var    versionTxtBlob = commit.Tree[candidatePath]?.Target as LibGit2Sharp.Blob;
                if (versionTxtBlob != null)
                {
                    if (blobVersionCache is null || !blobVersionCache.TryGetValue(versionTxtBlob.Id, out VersionOptions result))
                    {
                        result = TryReadVersionFile(new StreamReader(versionTxtBlob.GetContentStream()));
                        if (blobVersionCache is object)
                        {
                            result?.Freeze();
                            blobVersionCache.Add(versionTxtBlob.Id, result);
                        }
                    }

                    if (result != null)
                    {
                        return(result);
                    }
                }

                candidatePath = Path.Combine(searchDirectory, JsonFileName).Replace('\\', '/');
                var versionJsonBlob = commit.Tree[candidatePath]?.Target as LibGit2Sharp.Blob;
                if (versionJsonBlob != null)
                {
                    string versionJsonContent = null;
                    if (blobVersionCache is null || !blobVersionCache.TryGetValue(versionJsonBlob.Id, out VersionOptions result))
                    {
                        using (var sr = new StreamReader(versionJsonBlob.GetContentStream()))
                        {
                            versionJsonContent = sr.ReadToEnd();
                        }

                        try
                        {
                            result = TryReadVersionJsonContent(versionJsonContent, searchDirectory);
                        }
                        catch (FormatException ex)
                        {
                            throw new FormatException(
                                      $"Failure while reading {JsonFileName} from commit {commit.Sha}. " +
                                      "Fix this commit with rebase if this is an error, or review this doc on how to migrate to Nerdbank.GitVersioning: " +
                                      "https://github.com/dotnet/Nerdbank.GitVersioning/blob/master/doc/migrating.md", ex);
                        }

                        if (blobVersionCache is object)
                        {
                            result?.Freeze();
                            blobVersionCache.Add(versionJsonBlob.Id, result);
                        }
                    }

                    if (result?.Inherit ?? false)
                    {
                        if (parentDirectory != null)
                        {
                            result = GetVersion(commit, parentDirectory, blobVersionCache);
                            if (result != null)
                            {
                                if (versionJsonContent is null)
                                {
                                    // We reused a cache VersionOptions, but now we need the actual JSON string.
                                    using (var sr = new StreamReader(versionJsonBlob.GetContentStream()))
                                    {
                                        versionJsonContent = sr.ReadToEnd();
                                    }
                                }

                                if (result.IsFrozen)
                                {
                                    result = new VersionOptions(result);
                                }

                                JsonConvert.PopulateObject(versionJsonContent, result, VersionOptions.GetJsonSettings(repoRelativeBaseDirectory: searchDirectory));
                                return(result);
                            }
                        }

                        throw new InvalidOperationException($"\"{candidatePath}\" inherits from a parent directory version.json file but none exists.");
                    }
                    else if (result != null)
                    {
                        return(result);
                    }
                }

                searchDirectory = parentDirectory;
            }

            return(null);
        }