/// <summary>
        /// Retrieves a hash for the given file, either cached from this file content table or by hashing the file.
        /// If the file must be hashed (cache miss), the computed hash is stored in the file content table.
        /// </summary>
        /// <exception cref="BuildXLException">Thrown if accessing the local path specified by 'key' fails.</exception>
        public static async Task <VersionedFileIdentityAndContentInfoWithOrigin> GetAndRecordContentHashAsync(
            this FileContentTable fileContentTable,
            FileStream contentStream,
            bool?strict = default,
            bool ignoreKnownContentHash = false)
        {
            Contract.Requires(fileContentTable != null);
            Contract.Requires(contentStream != null);

            if (!ignoreKnownContentHash)
            {
                VersionedFileIdentityAndContentInfo?existingInfo = fileContentTable.TryGetKnownContentHash(contentStream);

                if (existingInfo.HasValue)
                {
                    return(new VersionedFileIdentityAndContentInfoWithOrigin(existingInfo.Value, ContentHashOrigin.Cached));
                }
            }

            ContentHash newHash = await ContentHashingUtilities.HashContentStreamAsync(contentStream);

            VersionedFileIdentityAndContentInfo newInfo = fileContentTable.RecordContentHash(
                contentStream,
                newHash,
                strict: strict);

            return(new VersionedFileIdentityAndContentInfoWithOrigin(newInfo, ContentHashOrigin.NewlyHashed));
        }