From 83306fdcd69ed838a6b0ee449e5fbbfe8072929f Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 6 May 2022 15:23:24 -0400 Subject: [PATCH 01/47] firestore.cmake: remove the snappy patch and just update the leveldb version --- cmake/external/firestore.cmake | 20 +- cmake/external/firestore_patch.py | 122 +++++ cmake/external/firestore_patch_test.py | 265 +++++++++ cmake/external/firestore_snappy.patch.txt | 619 ---------------------- cmake/external/leveldb.cmake | 1 + 5 files changed, 406 insertions(+), 621 deletions(-) create mode 100644 cmake/external/firestore_patch.py create mode 100644 cmake/external/firestore_patch_test.py delete mode 100644 cmake/external/firestore_snappy.patch.txt diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index 7cb97c0ce9..c9f8f3c020 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -18,6 +18,14 @@ if(TARGET firestore) return() endif() +if(${CMAKE_VERSION} VERSION_LESS "3.12") + include(FindPythonInterp) + set(MY_PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}") +else() + find_package(Python3 COMPONENTS Interpreter REQUIRED) + set(MY_PYTHON_EXECUTABLE "${Python3_EXECUTABLE}") +endif() + # If the format of the line below changes, then be sure to update # https://github.com/firebase/firebase-cpp-sdk/blob/fd054fa016/.github/workflows/update-dependencies.yml#L81 set(version CocoaPods-9.0.0) @@ -36,7 +44,11 @@ function(GetReleasedDep) BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" - PATCH_COMMAND patch -Np1 -i ${CMAKE_CURRENT_LIST_DIR}/firestore_snappy.patch.txt + PATCH_COMMAND + ${MY_PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_LIST_DIR}/firestore_patch.py + --leveldb-version-from + ${CMAKE_CURRENT_LIST_DIR}/leveldb.cmake HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" ) endfunction() @@ -57,7 +69,11 @@ function(GetTag t) BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" - PATCH_COMMAND patch -Np1 -i ${CMAKE_CURRENT_LIST_DIR}/firestore_snappy.patch.txt + PATCH_COMMAND + ${MY_PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_LIST_DIR}/firestore_patch.py + --leveldb-version-from + ${CMAKE_CURRENT_LIST_DIR}/leveldb.cmake HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" ) endfunction() diff --git a/cmake/external/firestore_patch.py b/cmake/external/firestore_patch.py new file mode 100644 index 0000000000..b5b50a258e --- /dev/null +++ b/cmake/external/firestore_patch.py @@ -0,0 +1,122 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Modify the version in leveldb.cmake from the Firebase iOS SDK to match the +version from this C++ SDK. +""" + +import argparse +import os +import pathlib +import re +from typing import List, Tuple + + +VERSION_PATTERN = r"\s*set\s*\(\s*version\s+([^)\s]+)\s*\)\s*" +VERSION_EXPR = re.compile(VERSION_PATTERN, re.IGNORECASE) +URL_HASH_PATTERN = r"\s*URL_HASH\s+([0-9a-zA-Z=]+)\s*" +URL_HASH_EXPR = re.compile(URL_HASH_PATTERN, re.IGNORECASE) + + +def main() -> None: + (src_file, dest_file) = parse_args() + + leveldb_version = load_value(src_file, VERSION_EXPR) + url_hash = load_value(src_file, URL_HASH_EXPR) + + set_value(dest_file, VERSION_EXPR, leveldb_version) + set_value(dest_file, URL_HASH_EXPR, url_hash) + + +def parse_args() -> Tuple[pathlib.Path, pathlib.Path]: + arg_parser = argparse.ArgumentParser() + arg_parser.add_argument("--leveldb-version-from", required=True) + arg_parser.add_argument("--leveldb-version-to") + + parsed_args = arg_parser.parse_args() + + leveldb_cmake_src_file = pathlib.Path(parsed_args.leveldb_version_from) + + if parsed_args.leveldb_version_to: + leveldb_cmake_dest_file = pathlib.Path(parsed_args.leveldb_version_to) + else: + leveldb_cmake_dest_file = pathlib.Path.cwd() \ + / "cmake" / "external" / "leveldb.cmake" + + return (leveldb_cmake_src_file, leveldb_cmake_dest_file) + + +def load_value(file_: pathlib.Path, expr: re.Pattern) -> str: + value = None + value_line = None + value_line_number = None + + with file_.open("rt", encoding="utf8") as f: + for (line_number, line) in enumerate(f, start=1): + match = expr.fullmatch(line) + if not match: + continue + elif value is not None: + raise RegexMatchError( + f"Multiple lines matching regex {expr.pattern} found in " + f"{file_}: line {value_line_number}, {value_line.strip()} " + f"and line {line_number}, {line.strip()}") + + value = match.group(1).strip() + value_line = line + value_line_number = line_number + + if value is None: + raise RegexMatchError( + f"No line matching regex {expr.pattern} found in {file_}") + + return value + + +def set_value(file_: pathlib.Path, expr: re.Pattern, version: str) -> None: + with file_.open("rt", encoding="utf8") as f: + lines = list(f) + + matching_line = None + matching_line_number = None + + for (line_number, line) in enumerate(lines, start=1): + match = expr.fullmatch(line) + if not match: + continue + elif matching_line is not None: + raise RegexMatchError( + f"Multiple lines matching regex {expr.pattern} found in " + f"{file_}: line {matching_line_number}, {matching_line.strip()} " + f"and line {line_number}, {line.strip()}") + + lines[line_number - 1] = line[:match.start(1)] + version + line[match.end(1):] + matching_line = line + matching_line_number = line_number + + if matching_line is None: + raise RegexMatchError( + f"No line matching regex {expr.pattern} found in {file_}") + + with file_.open("wt", encoding="utf8") as f: + f.writelines(lines) + + +class RegexMatchError(Exception): + pass + + +if __name__ == "__main__": + main() diff --git a/cmake/external/firestore_patch_test.py b/cmake/external/firestore_patch_test.py new file mode 100644 index 0000000000..bf739be555 --- /dev/null +++ b/cmake/external/firestore_patch_test.py @@ -0,0 +1,265 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import pathlib +import re +import shutil +import tempfile +from typing import Iterable +import unittest +import unittest.mock + +import firestore_patch + + +class TestUtilsMixin: + + def create_temp_file_with_lines(self, lines: Iterable[str]) -> pathlib.Path: + (handle, path_str) = tempfile.mkstemp() + os.close(handle) + path = pathlib.Path(path_str) + self.addCleanup(path.unlink, missing_ok=True) # pytype: disable=attribute-error + + with path.open("wt", encoding="utf8") as f: + for line in lines: + print(line, file=f) + + return path + + def create_temp_file_with_line(self, line: str) -> pathlib.Path: + return self.create_temp_file_with_lines([line]) + + +class MainTest(TestUtilsMixin, unittest.TestCase): + + def test(self): + src_file = self.create_temp_file_with_lines([ + "aaa", + "bbb", + "set(version 1.2.3)", + "URL_HASH SHA256=abcdef", + "ccc", + "ddd", + ]) + dest_file = self.create_temp_file_with_lines([ + "aaa", + "bbb", + "set(version 4.5.6)", + "URL_HASH SHA256=ghijkl", + "ccc", + "ddd", + ]) + dest_file_contents_before = dest_file.read_text(encoding="utf8") + patcher = unittest.mock.patch.object( + firestore_patch, + "parse_args", + spec_set=True, + autospec=True, + return_value=(src_file, dest_file) + ) + + with patcher: + firestore_patch.main() + + dest_file_contents_after = dest_file.read_text(encoding="utf8") + self.assertEqual( + dest_file_contents_after, + dest_file_contents_before + .replace("4.5.6", "1.2.3") + .replace("ghijkl", "abcdef") + ) + + +class VersionExprTest(TestUtilsMixin, unittest.TestCase): + + def test_matches_semantic_version(self): + path = self.create_temp_file_with_line("set(version 1.2.3)") + + value = firestore_patch.load_value(path, firestore_patch.VERSION_EXPR) + + self.assertEqual(value, "1.2.3") + + def test_matches_sha1(self): + path = self.create_temp_file_with_line("set(version fd054fa01)") + + value = firestore_patch.load_value(path, firestore_patch.VERSION_EXPR) + + self.assertEqual(value, "fd054fa01") + + def test_ignores_whitespace(self): + path = self.create_temp_file_with_line(" set ( version 1.2.3 ) ") + + value = firestore_patch.load_value(path, firestore_patch.VERSION_EXPR) + + self.assertEqual(value, "1.2.3") + + def test_case_insensitive(self): + path = self.create_temp_file_with_line("sEt(vErSiOn 1.2.3)") + + value = firestore_patch.load_value(path, firestore_patch.VERSION_EXPR) + + self.assertEqual(value, "1.2.3") + + +class UrlHashExprTest(TestUtilsMixin, unittest.TestCase): + + def test_matches_sha256(self): + path = self.create_temp_file_with_line("URL_HASH SHA256=abc123def456") + + value = firestore_patch.load_value(path, firestore_patch.URL_HASH_EXPR) + + self.assertEqual(value, "SHA256=abc123def456") + + def test_ignores_whitespace(self): + path = self.create_temp_file_with_line(" URL_HASH abc123def456 ") + + value = firestore_patch.load_value(path, firestore_patch.URL_HASH_EXPR) + + self.assertEqual(value, "abc123def456") + + def test_case_insensitive(self): + path = self.create_temp_file_with_line("UrL_hAsH Sha256=abc123def456") + + value = firestore_patch.load_value(path, firestore_patch.URL_HASH_EXPR) + + self.assertEqual(value, "Sha256=abc123def456") + + +class LoadValueTest(TestUtilsMixin, unittest.TestCase): + + def test_loads_the_value(self): + path = self.create_temp_file_with_line("aaa1234ccc") + expr = re.compile(r"\D+(\d+)\D+") + + value = firestore_patch.load_value(path, expr) + + self.assertEqual(value, "1234") + + def test_loads_the_value_ignoring_non_matching_lines(self): + path = self.create_temp_file_with_lines([ + "blah", + "blah", + "aaa1234cccc", + "blah", + "blah", + ]) + expr = re.compile(r"\D+(\d+)\D+") + + value = firestore_patch.load_value(path, expr) + + self.assertEqual(value, "1234") + + def test_raises_error_if_no_matching_line_found(self): + path = self.create_temp_file_with_lines([ + "blah", + "blah", + "blah", + "blah", + ]) + expr = re.compile(r"\D+(\d+)\D+") + + with self.assertRaises(firestore_patch.RegexMatchError) as cm: + firestore_patch.load_value(path, expr) + + self.assertIn("no line matching", str(cm.exception).lower()) + self.assertIn(expr.pattern, str(cm.exception)) + self.assertIn(str(path), str(cm.exception)) + + def test_raises_error_if_multiple_matching_lines_found(self): + lines = ["blah"] * 100 + lines.append("aaa123bbb") + lines.append("ccc456ddd") + path = self.create_temp_file_with_lines(lines) + expr = re.compile(r"\D+(\d+)\D+") + + with self.assertRaises(firestore_patch.RegexMatchError) as cm: + firestore_patch.load_value(path, expr) + + self.assertIn("multiple lines matching", str(cm.exception).lower()) + self.assertIn(str(path), str(cm.exception)) + self.assertIn(expr.pattern, str(cm.exception)) + self.assertIn("line 101", str(cm.exception)) + self.assertIn("line 102", str(cm.exception)) + self.assertIn("123", str(cm.exception)) + self.assertIn("456", str(cm.exception)) + + +class SaveValueTest(TestUtilsMixin, unittest.TestCase): + + def test_saves_the_value(self): + path = self.create_temp_file_with_line("aaa1234ccc") + expr = re.compile(r"\D+(\d+)\D+") + + firestore_patch.set_value(path, expr, "9876") + + new_value = firestore_patch.load_value(path, expr) + self.assertEqual(new_value, "9876") + + def test_saves_the_value_ignoring_non_matching_lines(self): + path = self.create_temp_file_with_lines([ + "blah", + "blah", + "aaa1234cccc", + "blah", + "blah", + ]) + expr = re.compile(r"\D+(\d+)\D+") + file_contents_before = path.read_text(encoding="utf8") + + firestore_patch.set_value(path, expr, "9876") + + file_contents_after = path.read_text(encoding="utf8") + self.assertEqual( + file_contents_after, + file_contents_before.replace("1234", "9876"), + ) + + def test_raises_error_if_no_matching_line_found(self): + path = self.create_temp_file_with_lines([ + "blah", + "blah", + "blah", + "blah", + ]) + expr = re.compile(r"\D+(\d+)\D+") + + with self.assertRaises(firestore_patch.RegexMatchError) as cm: + firestore_patch.set_value(path, expr, "") + + self.assertIn("no line matching", str(cm.exception).lower()) + self.assertIn(expr.pattern, str(cm.exception)) + self.assertIn(str(path), str(cm.exception)) + + def test_raises_error_if_multiple_matching_lines_found(self): + lines = ["blah"] * 100 + lines.append("aaa123bbb") + lines.append("ccc456ddd") + path = self.create_temp_file_with_lines(lines) + expr = re.compile(r"\D+(\d+)\D+") + + with self.assertRaises(firestore_patch.RegexMatchError) as cm: + firestore_patch.set_value(path, expr, "") + + self.assertIn("multiple lines matching", str(cm.exception).lower()) + self.assertIn(str(path), str(cm.exception)) + self.assertIn(expr.pattern, str(cm.exception)) + self.assertIn("line 101", str(cm.exception)) + self.assertIn("line 102", str(cm.exception)) + self.assertIn("123", str(cm.exception)) + self.assertIn("456", str(cm.exception)) + + +if __name__ == "__main__": + unittest.main() diff --git a/cmake/external/firestore_snappy.patch.txt b/cmake/external/firestore_snappy.patch.txt deleted file mode 100644 index 317ecc6823..0000000000 --- a/cmake/external/firestore_snappy.patch.txt +++ /dev/null @@ -1,619 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 29458bf13..7be37691d 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -227,6 +227,12 @@ if(NOT ZLIB_FOUND) - endif() - - -+# Snappy -+set(SNAPPY_BUILD_TESTS OFF CACHE BOOL "Firestore disabled") -+set(SNAPPY_BUILD_BENCHMARKS OFF CACHE BOOL "Firestore disabled") -+add_external_subdirectory(snappy) -+firebase_ios_add_alias(Snappy::Snappy snappy) -+ - # LevelDB - set(LEVELDB_BUILD_TESTS OFF CACHE BOOL "Firestore disabled") - set(LEVELDB_BUILD_BENCHMARKS OFF CACHE BOOL "Firestore disabled") -diff --git a/cmake/external/CMakeLists.txt b/cmake/external/CMakeLists.txt -index 2179633a8..c1de37b6d 100644 ---- a/cmake/external/CMakeLists.txt -+++ b/cmake/external/CMakeLists.txt -@@ -35,6 +35,7 @@ include(c-ares) - include(googletest) - include(GoogleUtilities) - include(grpc) -+include(snappy) - include(leveldb) - include(libfuzzer) - include(nanopb) -diff --git a/cmake/external/leveldb.cmake b/cmake/external/leveldb.cmake -index b71a77535..2556d7041 100644 ---- a/cmake/external/leveldb.cmake -+++ b/cmake/external/leveldb.cmake -@@ -13,20 +13,27 @@ - # limitations under the License. - - include(ExternalProject) -+include(FindPythonInterp) - - if(TARGET leveldb) - return() - endif() - --set(version 1.22) -+set(version 1.23) -+ -+ExternalProject_Get_property(snappy SOURCE_DIR) -+set(snappy_source_dir "${SOURCE_DIR}") -+ExternalProject_Get_property(snappy BINARY_DIR) -+set(snappy_binary_dir "${BINARY_DIR}") - - ExternalProject_Add( - leveldb - -+ DEPENDS snappy -+ - DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} - DOWNLOAD_NAME leveldb-${version}.tar.gz - URL https://github.com/google/leveldb/archive/${version}.tar.gz -- URL_HASH SHA256=55423cac9e3306f4a9502c738a001e4a339d1a38ffbee7572d4a07d5d63949b2 - - PREFIX ${PROJECT_BINARY_DIR} - -@@ -34,6 +41,7 @@ ExternalProject_Add( - BUILD_COMMAND "" - INSTALL_COMMAND "" - TEST_COMMAND "" -+ PATCH_COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/leveldb_patch.py --snappy-source-dir ${snappy_source_dir} --snappy-binary-dir ${snappy_binary_dir} - - HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" - ) -diff --git a/cmake/external/leveldb_patch.py b/cmake/external/leveldb_patch.py -new file mode 100644 -index 000000000..51a62d54a ---- /dev/null -+++ b/cmake/external/leveldb_patch.py -@@ -0,0 +1,144 @@ -+# Copyright 2022 Google LLC -+# -+# Licensed under the Apache License, Version 2.0 (the "License"); -+# you may not use this file except in compliance with the License. -+# You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+ -+""" -+Modify the CMakeLists.txt from LevelDb to staticly link Snappy compression -+support. -+""" -+ -+import argparse -+import dataclasses -+import os -+import pathlib -+from typing import Iterable, Sequence -+ -+ -+def main() -> None: -+ arg_parser = argparse.ArgumentParser() -+ arg_parser.add_argument("--snappy-source-dir", required=True) -+ arg_parser.add_argument("--snappy-binary-dir", required=True) -+ parsed_args = arg_parser.parse_args() -+ del arg_parser -+ snappy_source_dir = pathlib.Path(parsed_args.snappy_source_dir) -+ snappy_binary_dir = pathlib.Path(parsed_args.snappy_binary_dir) -+ del parsed_args -+ -+ cmakelists_txt_file = pathlib.Path("CMakeLists.txt") -+ with cmakelists_txt_file.open("rt", encoding="utf8") as f: -+ lines = tuple(f) -+ -+ patcher = CMakeListsPatcher( -+ lines, -+ os.path.abspath(__file__), -+ snappy_source_dir, -+ snappy_binary_dir, -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ with cmakelists_txt_file.open("wt", encoding="utf8") as f: -+ f.writelines(patched_lines) -+ -+ -+@dataclasses.dataclass(frozen=True) -+class LineComponents: -+ full: str -+ indent: str -+ line: str -+ eol: str -+ -+ -+class CMakeListsPatcher: -+ -+ SNAPPY_DETECT_LINE = \ -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""" -+ SNAPPY_INCLUDE_LINE = \ -+ "target_include_directories(leveldb" -+ SNAPPY_LINK_LINE = \ -+ "target_link_libraries(leveldb snappy)" -+ -+ def __init__( -+ self, -+ lines: Sequence[str], -+ script_name: str, -+ snappy_source_dir: pathlib.Path, -+ snappy_binary_dir: pathlib.Path) -> None: -+ self.i = 0 -+ self.lines = lines -+ self.script_name = script_name -+ self.snappy_source_dir_str = snappy_source_dir.as_posix() -+ self.snappy_binary_dir_str = snappy_binary_dir.as_posix() -+ -+ def patch(self) -> Iterable[str]: -+ while self.i < len(self.lines): -+ full_line = self.lines[self.i] -+ line = self._split_line(full_line) -+ self.i += 1 -+ -+ if line.line == self.SNAPPY_DETECT_LINE: -+ yield from self._on_snappy_detect_line(line) -+ elif line.line == self.SNAPPY_INCLUDE_LINE: -+ yield full_line -+ yield from self._on_leveldb_include_start() -+ elif line.line == self.SNAPPY_LINK_LINE: -+ yield from self._on_leveldb_snappy_link_line(line) -+ else: -+ yield full_line -+ -+ def _begin_mod_line(self, mod_name: str) -> str: -+ return f"# BEGIN: {mod_name} modification by {self.script_name}" -+ -+ def _end_mod_line(self, mod_name: str) -> str: -+ return f"# END: {mod_name} modification by {self.script_name}" -+ -+ def _on_snappy_detect_line(self, line: LineComponents) -> Iterable[str]: -+ yield self._begin_mod_line("snappy_detect_line") + line.eol -+ yield line.indent + "# " + line.line + line.eol -+ yield line.indent + """set(HAVE_SNAPPY ON CACHE BOOL "")""" + line.eol -+ yield self._end_mod_line("snappy_detect_line") + line.eol -+ -+ def _on_leveldb_include_start(self) -> Iterable[str]: -+ line1 = self._split_line(self.lines[self.i]) -+ line2 = self._split_line(self.lines[self.i + 1]) -+ begin_mod_line = self._begin_mod_line("leveldb_include_start") -+ -+ if line1.line == begin_mod_line: -+ return -+ -+ yield begin_mod_line + line1.eol -+ yield line1.indent + "PRIVATE" + line1.eol -+ yield line2.indent + self.snappy_source_dir_str + line2.eol -+ yield line2.indent + self.snappy_binary_dir_str + line2.eol -+ yield self._end_mod_line("leveldb_include_start") + line1.eol -+ -+ def _on_leveldb_snappy_link_line(self, line: LineComponents) -> Iterable[str]: -+ yield self._begin_mod_line("leveldb_snappy_link_line") + line.eol -+ yield line.indent + "# " + line.line + line.eol -+ yield line.indent + f"target_link_libraries(leveldb Snappy::Snappy)" + line.eol -+ yield self._end_mod_line("leveldb_snappy_link_line") + line.eol -+ -+ def _split_line(self, line: str) -> LineComponents: -+ line_rstripped = line.rstrip() -+ eol = line[len(line_rstripped):] -+ line_stripped = line_rstripped.strip() -+ indent = line_rstripped[:len(line_rstripped) - len(line_stripped)] -+ return LineComponents(full=line, indent=indent, line=line_stripped, eol=eol) -+ -+ -+class LeveDbPatchException(Exception): -+ pass -+ -+ -+if __name__ == "__main__": -+ main() -diff --git a/cmake/external/leveldb_patch_test.py b/cmake/external/leveldb_patch_test.py -new file mode 100644 -index 000000000..b1d62526b ---- /dev/null -+++ b/cmake/external/leveldb_patch_test.py -@@ -0,0 +1,328 @@ -+# Copyright 2022 Google LLC -+# -+# Licensed under the Apache License, Version 2.0 (the "License"); -+# you may not use this file except in compliance with the License. -+# You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+ -+import leveldb_patch -+import pathlib -+import unittest -+ -+ -+class CMakeListsPatcherTest(unittest.TestCase): -+ -+ def setUp(self): -+ super().setUp() -+ self.sample_snappy_source_dir = pathlib.Path("a/b/snappy_source_dir") -+ self.sample_snappy_binary_dir = pathlib.Path("a/b/snappy_binary_dir") -+ -+ def test_snappy_detect_line_is_commented_and_replaced(self): -+ lines = ( -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ "MyCoolScript", -+ self.sample_snappy_source_dir, -+ self.sample_snappy_binary_dir, -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: snappy_detect_line modification by MyCoolScript", -+ """# check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ """set(HAVE_SNAPPY ON CACHE BOOL "")""", -+ "# END: snappy_detect_line modification by MyCoolScript", -+ ]) -+ -+ def test_snappy_detect_line_has_indent_and_eol_preserved(self): -+ lines = ( -+ """ check_library_exists(snappy snappy_compress "" HAVE_SNAPPY) \n""", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ "MyCoolScript", -+ self.sample_snappy_source_dir, -+ self.sample_snappy_binary_dir, -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: snappy_detect_line modification by MyCoolScript \n", -+ """ # check_library_exists(snappy snappy_compress "" HAVE_SNAPPY) \n""", -+ """ set(HAVE_SNAPPY ON CACHE BOOL "") \n""", -+ "# END: snappy_detect_line modification by MyCoolScript \n", -+ ]) -+ -+ def test_snappy_detect_line_does_not_affect_surrounding_lines(self): -+ lines = ( -+ "aaa", -+ "bbb", -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ "ccc", -+ "ddd", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ "MyCoolScript", -+ self.sample_snappy_source_dir, -+ self.sample_snappy_binary_dir, -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "aaa", -+ "bbb", -+ "# BEGIN: snappy_detect_line modification by MyCoolScript", -+ """# check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ """set(HAVE_SNAPPY ON CACHE BOOL "")""", -+ "# END: snappy_detect_line modification by MyCoolScript", -+ "ccc", -+ "ddd", -+ ]) -+ -+ def test_snappy_include_is_amended(self): -+ lines = ( -+ "target_include_directories(leveldb", -+ "PUBLIC", -+ "path1", -+ "path2", -+ ")", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "target_include_directories(leveldb", -+ "# BEGIN: leveldb_include_start modification by MyCoolSript", -+ "PRIVATE", -+ "a/b", -+ "c/d", -+ "# END: leveldb_include_start modification by MyCoolSript", -+ "PUBLIC", -+ "path1", -+ "path2", -+ ")", -+ ]) -+ -+ def test_snappy_include_lines_adopt_indenting_and_eol_convention(self): -+ lines = ( -+ "target_include_directories(leveldb\n", -+ " PUBLIC \n", -+ " path1 \n", -+ " path2 \n", -+ ")\n", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "target_include_directories(leveldb\n", -+ "# BEGIN: leveldb_include_start modification by MyCoolSript \n", -+ " PRIVATE \n", -+ " a/b \n", -+ " c/d \n", -+ "# END: leveldb_include_start modification by MyCoolSript \n", -+ " PUBLIC \n", -+ " path1 \n", -+ " path2 \n", -+ ")\n", -+ ]) -+ -+ def test_snappy_include_line_does_not_affect_surrounding_lines(self): -+ lines = ( -+ "aaa", -+ "bbb", -+ "target_include_directories(leveldb", -+ "PUBLIC", -+ "path1", -+ "path2", -+ ")", -+ "ccc", -+ "ddd", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "aaa", -+ "bbb", -+ "target_include_directories(leveldb", -+ "# BEGIN: leveldb_include_start modification by MyCoolSript", -+ "PRIVATE", -+ "a/b", -+ "c/d", -+ "# END: leveldb_include_start modification by MyCoolSript", -+ "PUBLIC", -+ "path1", -+ "path2", -+ ")", -+ "ccc", -+ "ddd", -+ ]) -+ -+ def test_leveldb_snappy_link_line_is_commented_and_replaced(self): -+ lines = ( -+ "target_link_libraries(leveldb snappy)", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript", -+ "# target_link_libraries(leveldb snappy)", -+ "target_link_libraries(leveldb Snappy::Snappy)", -+ "# END: leveldb_snappy_link_line modification by MyCoolSript", -+ ]) -+ -+ def test_leveldb_snappy_link_line_has_indent_and_eol_preserved(self): -+ lines = ( -+ " target_link_libraries(leveldb snappy) \n", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript \n", -+ " # target_link_libraries(leveldb snappy) \n", -+ " target_link_libraries(leveldb Snappy::Snappy) \n", -+ "# END: leveldb_snappy_link_line modification by MyCoolSript \n", -+ ]) -+ -+ def test_leveldb_snappy_link_line_does_not_affect_surrounding_lines(self): -+ lines = ( -+ "aaa", -+ "bbb", -+ "target_link_libraries(leveldb snappy)", -+ "ccc", -+ "ddd", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "aaa", -+ "bbb", -+ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript", -+ "# target_link_libraries(leveldb snappy)", -+ "target_link_libraries(leveldb Snappy::Snappy)", -+ "# END: leveldb_snappy_link_line modification by MyCoolSript", -+ "ccc", -+ "ddd", -+ ]) -+ -+ def test_all_patches_combined(self): -+ lines = ( -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ "target_include_directories(leveldb", -+ "PUBLIC", -+ "path1", -+ ")", -+ "target_link_libraries(leveldb snappy)", -+ ) -+ -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: snappy_detect_line modification by MyCoolSript", -+ """# check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ """set(HAVE_SNAPPY ON CACHE BOOL "")""", -+ "# END: snappy_detect_line modification by MyCoolSript", -+ "target_include_directories(leveldb", -+ "# BEGIN: leveldb_include_start modification by MyCoolSript", -+ "PRIVATE", -+ "a/b", -+ "c/d", -+ "# END: leveldb_include_start modification by MyCoolSript", -+ "PUBLIC", -+ "path1", -+ ")", -+ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript", -+ "# target_link_libraries(leveldb snappy)", -+ "target_link_libraries(leveldb Snappy::Snappy)", -+ "# END: leveldb_snappy_link_line modification by MyCoolSript", -+ ]) -+ -+ def test_idempotence(self): -+ lines = ( -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)\n""", -+ "target_include_directories(leveldb", -+ "PUBLIC", -+ "path1", -+ ")", -+ "target_link_libraries(leveldb snappy)", -+ ) -+ -+ patcher1 = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ patched_lines1 = tuple(patcher1.patch()) -+ patcher2 = leveldb_patch.CMakeListsPatcher( -+ patched_lines1, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ patched_lines2 = tuple(patcher2.patch()) -+ -+ self.assertSequenceEqual(patched_lines1, patched_lines2) -+ -+ -+if __name__ == "__main__": -+ unittest.main() -diff --git a/cmake/external/snappy.cmake b/cmake/external/snappy.cmake -new file mode 100644 -index 000000000..9f25c03d0 ---- /dev/null -+++ b/cmake/external/snappy.cmake -@@ -0,0 +1,40 @@ -+# Copyright 2022 Google LLC -+# -+# Licensed under the Apache License, Version 2.0 (the "License"); -+# you may not use this file except in compliance with the License. -+# You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+ -+include(ExternalProject) -+ -+if(TARGET snappy) -+ return() -+endif() -+ -+set(version 1.1.9) -+ -+ExternalProject_Add( -+ snappy -+ -+ DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} -+ DOWNLOAD_NAME snappy-${version}.tar.gz -+ URL https://github.com/google/snappy/archive/refs/tags/${version}.tar.gz -+ URL_HASH SHA256=75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7 -+ -+ PREFIX ${PROJECT_BINARY_DIR} -+ -+ CONFIGURE_COMMAND "" -+ BUILD_COMMAND "" -+ INSTALL_COMMAND "" -+ TEST_COMMAND "" -+ PATCH_COMMAND patch -Np1 -i ${CMAKE_CURRENT_LIST_DIR}/snappy.patch -+ -+ HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" -+) -diff --git a/cmake/external/snappy.patch b/cmake/external/snappy.patch -new file mode 100644 -index 000000000..28bfb0837 ---- /dev/null -+++ b/cmake/external/snappy.patch -@@ -0,0 +1,12 @@ -+diff -Naur snappy/snappy.cc snappy_patched/snappy.cc -+--- snappy/snappy.cc 2022-04-12 20:44:55.000000000 -0400 -++++ snappy_patched/snappy.cc 2022-04-12 20:47:05.000000000 -0400 -+@@ -1014,7 +1014,7 @@ -+ } -+ -+ SNAPPY_ATTRIBUTE_ALWAYS_INLINE -+-size_t AdvanceToNextTag(const uint8_t** ip_p, size_t* tag) { -++inline size_t AdvanceToNextTag(const uint8_t** ip_p, size_t* tag) { -+ const uint8_t*& ip = *ip_p; -+ // This section is crucial for the throughput of the decompression loop. -+ // The latency of an iteration is fundamentally constrained by the diff --git a/cmake/external/leveldb.cmake b/cmake/external/leveldb.cmake index 18970659a4..a8a154bb4e 100644 --- a/cmake/external/leveldb.cmake +++ b/cmake/external/leveldb.cmake @@ -26,6 +26,7 @@ ExternalProject_Add( DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} DOWNLOAD_NAME leveldb-${version}.tar.gz URL https://github.com/google/leveldb/archive/${version}.tar.gz + URL_HASH SHA256=9a37f8a6174f09bd622bc723b55881dc541cd50747cbd08831c2a82d620f6d76 PREFIX ${PROJECT_BINARY_DIR} From 346a4a4109cd33db553de0f700d4a52bad57cb92 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 9 May 2022 18:34:39 +0000 Subject: [PATCH 02/47] REVERT ME: Pin firebase-ios-sdk to https://github.com/firebase/firebase-ios-sdk/pull/9596/commits/ece67740ac77e95de658471e4b3d63161d5df5f0 --- cmake/external/firestore.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index c9f8f3c020..75891eeafb 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -36,7 +36,10 @@ function(GetReleasedDep) firestore DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} - URL https://github.com/firebase/firebase-ios-sdk/archive/${version}.tar.gz + GIT_REPOSITORY "https://github.com/firebase/firebase-ios-sdk.git" + # Pinned commit from https://github.com/firebase/firebase-ios-sdk/pull/9596 + # (Enable Snappy compression support in LevelDb in cmake builds) + GIT_TAG ece67740ac77e95de658471e4b3d63161d5df5f0 PREFIX ${PROJECT_BINARY_DIR} From 57d03a9cebd16f05cda61472c8b562e11ce80525 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 20 May 2022 14:05:25 -0400 Subject: [PATCH 03/47] firestore.cmake: updated pinned firebase-ios-sdk to HEAD now that the PR that adds Snappy support has been merged there --- cmake/external/firestore.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index 75891eeafb..e7c6898f58 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -37,9 +37,9 @@ function(GetReleasedDep) DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} GIT_REPOSITORY "https://github.com/firebase/firebase-ios-sdk.git" - # Pinned commit from https://github.com/firebase/firebase-ios-sdk/pull/9596 - # (Enable Snappy compression support in LevelDb in cmake builds) - GIT_TAG ece67740ac77e95de658471e4b3d63161d5df5f0 + # Pinned HEAD commit after https://github.com/firebase/firebase-ios-sdk/pull/9596 + # (Enable Snappy compression support in LevelDb in cmake builds) was merged. + GIT_TAG c0df0d4ab11d4ae30c307a0c7dcdb29e3e0dc411 PREFIX ${PROJECT_BINARY_DIR} From bdcbbbc5a84e36663497644280269cd87a6b5317 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 11 May 2022 04:35:52 +0000 Subject: [PATCH 04/47] CMakeLists.txt: set(RE2_BUILD_TESTING OFF CACHE BOOL "") --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb610fdc90..83b2a3fde5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,6 +214,9 @@ endif() # firebase-ios-sdk since it's not needed and can sometimes fail to build. set(FIRESTORE_INCLUDE_OBJC OFF CACHE BOOL "Disabled for the CPP SDK") +# Disable re2 build tests +set(RE2_BUILD_TESTING OFF CACHE BOOL "") + if(FIREBASE_CPP_USE_PRIOR_GRADLE_BUILD) # Quote meta characters in ${CMAKE_CURRENT_LIST_DIR} so we can # match it in a regex. From a1d4c3e6ed0b8adc38acd63f2fc499086ab033f3 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 11:34:37 -0400 Subject: [PATCH 05/47] Patch in https://github.com/firebase/firebase-cpp-sdk/pull/932 to get the C++ SDK to build successfully against HEAD of the firebase-ios-sdk --- CMakeLists.txt | 3 + cmake/external/firestore.cmake | 20 +- cmake/external/firestore_patch.py | 122 +++++ cmake/external/firestore_patch_test.py | 265 +++++++++ cmake/external/firestore_snappy.patch.txt | 619 ---------------------- cmake/external/leveldb.cmake | 1 + 6 files changed, 409 insertions(+), 621 deletions(-) create mode 100644 cmake/external/firestore_patch.py create mode 100644 cmake/external/firestore_patch_test.py delete mode 100644 cmake/external/firestore_snappy.patch.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index cb610fdc90..83b2a3fde5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,6 +214,9 @@ endif() # firebase-ios-sdk since it's not needed and can sometimes fail to build. set(FIRESTORE_INCLUDE_OBJC OFF CACHE BOOL "Disabled for the CPP SDK") +# Disable re2 build tests +set(RE2_BUILD_TESTING OFF CACHE BOOL "") + if(FIREBASE_CPP_USE_PRIOR_GRADLE_BUILD) # Quote meta characters in ${CMAKE_CURRENT_LIST_DIR} so we can # match it in a regex. diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index 7cb97c0ce9..c9f8f3c020 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -18,6 +18,14 @@ if(TARGET firestore) return() endif() +if(${CMAKE_VERSION} VERSION_LESS "3.12") + include(FindPythonInterp) + set(MY_PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}") +else() + find_package(Python3 COMPONENTS Interpreter REQUIRED) + set(MY_PYTHON_EXECUTABLE "${Python3_EXECUTABLE}") +endif() + # If the format of the line below changes, then be sure to update # https://github.com/firebase/firebase-cpp-sdk/blob/fd054fa016/.github/workflows/update-dependencies.yml#L81 set(version CocoaPods-9.0.0) @@ -36,7 +44,11 @@ function(GetReleasedDep) BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" - PATCH_COMMAND patch -Np1 -i ${CMAKE_CURRENT_LIST_DIR}/firestore_snappy.patch.txt + PATCH_COMMAND + ${MY_PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_LIST_DIR}/firestore_patch.py + --leveldb-version-from + ${CMAKE_CURRENT_LIST_DIR}/leveldb.cmake HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" ) endfunction() @@ -57,7 +69,11 @@ function(GetTag t) BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" - PATCH_COMMAND patch -Np1 -i ${CMAKE_CURRENT_LIST_DIR}/firestore_snappy.patch.txt + PATCH_COMMAND + ${MY_PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_LIST_DIR}/firestore_patch.py + --leveldb-version-from + ${CMAKE_CURRENT_LIST_DIR}/leveldb.cmake HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" ) endfunction() diff --git a/cmake/external/firestore_patch.py b/cmake/external/firestore_patch.py new file mode 100644 index 0000000000..b5b50a258e --- /dev/null +++ b/cmake/external/firestore_patch.py @@ -0,0 +1,122 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Modify the version in leveldb.cmake from the Firebase iOS SDK to match the +version from this C++ SDK. +""" + +import argparse +import os +import pathlib +import re +from typing import List, Tuple + + +VERSION_PATTERN = r"\s*set\s*\(\s*version\s+([^)\s]+)\s*\)\s*" +VERSION_EXPR = re.compile(VERSION_PATTERN, re.IGNORECASE) +URL_HASH_PATTERN = r"\s*URL_HASH\s+([0-9a-zA-Z=]+)\s*" +URL_HASH_EXPR = re.compile(URL_HASH_PATTERN, re.IGNORECASE) + + +def main() -> None: + (src_file, dest_file) = parse_args() + + leveldb_version = load_value(src_file, VERSION_EXPR) + url_hash = load_value(src_file, URL_HASH_EXPR) + + set_value(dest_file, VERSION_EXPR, leveldb_version) + set_value(dest_file, URL_HASH_EXPR, url_hash) + + +def parse_args() -> Tuple[pathlib.Path, pathlib.Path]: + arg_parser = argparse.ArgumentParser() + arg_parser.add_argument("--leveldb-version-from", required=True) + arg_parser.add_argument("--leveldb-version-to") + + parsed_args = arg_parser.parse_args() + + leveldb_cmake_src_file = pathlib.Path(parsed_args.leveldb_version_from) + + if parsed_args.leveldb_version_to: + leveldb_cmake_dest_file = pathlib.Path(parsed_args.leveldb_version_to) + else: + leveldb_cmake_dest_file = pathlib.Path.cwd() \ + / "cmake" / "external" / "leveldb.cmake" + + return (leveldb_cmake_src_file, leveldb_cmake_dest_file) + + +def load_value(file_: pathlib.Path, expr: re.Pattern) -> str: + value = None + value_line = None + value_line_number = None + + with file_.open("rt", encoding="utf8") as f: + for (line_number, line) in enumerate(f, start=1): + match = expr.fullmatch(line) + if not match: + continue + elif value is not None: + raise RegexMatchError( + f"Multiple lines matching regex {expr.pattern} found in " + f"{file_}: line {value_line_number}, {value_line.strip()} " + f"and line {line_number}, {line.strip()}") + + value = match.group(1).strip() + value_line = line + value_line_number = line_number + + if value is None: + raise RegexMatchError( + f"No line matching regex {expr.pattern} found in {file_}") + + return value + + +def set_value(file_: pathlib.Path, expr: re.Pattern, version: str) -> None: + with file_.open("rt", encoding="utf8") as f: + lines = list(f) + + matching_line = None + matching_line_number = None + + for (line_number, line) in enumerate(lines, start=1): + match = expr.fullmatch(line) + if not match: + continue + elif matching_line is not None: + raise RegexMatchError( + f"Multiple lines matching regex {expr.pattern} found in " + f"{file_}: line {matching_line_number}, {matching_line.strip()} " + f"and line {line_number}, {line.strip()}") + + lines[line_number - 1] = line[:match.start(1)] + version + line[match.end(1):] + matching_line = line + matching_line_number = line_number + + if matching_line is None: + raise RegexMatchError( + f"No line matching regex {expr.pattern} found in {file_}") + + with file_.open("wt", encoding="utf8") as f: + f.writelines(lines) + + +class RegexMatchError(Exception): + pass + + +if __name__ == "__main__": + main() diff --git a/cmake/external/firestore_patch_test.py b/cmake/external/firestore_patch_test.py new file mode 100644 index 0000000000..bf739be555 --- /dev/null +++ b/cmake/external/firestore_patch_test.py @@ -0,0 +1,265 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import pathlib +import re +import shutil +import tempfile +from typing import Iterable +import unittest +import unittest.mock + +import firestore_patch + + +class TestUtilsMixin: + + def create_temp_file_with_lines(self, lines: Iterable[str]) -> pathlib.Path: + (handle, path_str) = tempfile.mkstemp() + os.close(handle) + path = pathlib.Path(path_str) + self.addCleanup(path.unlink, missing_ok=True) # pytype: disable=attribute-error + + with path.open("wt", encoding="utf8") as f: + for line in lines: + print(line, file=f) + + return path + + def create_temp_file_with_line(self, line: str) -> pathlib.Path: + return self.create_temp_file_with_lines([line]) + + +class MainTest(TestUtilsMixin, unittest.TestCase): + + def test(self): + src_file = self.create_temp_file_with_lines([ + "aaa", + "bbb", + "set(version 1.2.3)", + "URL_HASH SHA256=abcdef", + "ccc", + "ddd", + ]) + dest_file = self.create_temp_file_with_lines([ + "aaa", + "bbb", + "set(version 4.5.6)", + "URL_HASH SHA256=ghijkl", + "ccc", + "ddd", + ]) + dest_file_contents_before = dest_file.read_text(encoding="utf8") + patcher = unittest.mock.patch.object( + firestore_patch, + "parse_args", + spec_set=True, + autospec=True, + return_value=(src_file, dest_file) + ) + + with patcher: + firestore_patch.main() + + dest_file_contents_after = dest_file.read_text(encoding="utf8") + self.assertEqual( + dest_file_contents_after, + dest_file_contents_before + .replace("4.5.6", "1.2.3") + .replace("ghijkl", "abcdef") + ) + + +class VersionExprTest(TestUtilsMixin, unittest.TestCase): + + def test_matches_semantic_version(self): + path = self.create_temp_file_with_line("set(version 1.2.3)") + + value = firestore_patch.load_value(path, firestore_patch.VERSION_EXPR) + + self.assertEqual(value, "1.2.3") + + def test_matches_sha1(self): + path = self.create_temp_file_with_line("set(version fd054fa01)") + + value = firestore_patch.load_value(path, firestore_patch.VERSION_EXPR) + + self.assertEqual(value, "fd054fa01") + + def test_ignores_whitespace(self): + path = self.create_temp_file_with_line(" set ( version 1.2.3 ) ") + + value = firestore_patch.load_value(path, firestore_patch.VERSION_EXPR) + + self.assertEqual(value, "1.2.3") + + def test_case_insensitive(self): + path = self.create_temp_file_with_line("sEt(vErSiOn 1.2.3)") + + value = firestore_patch.load_value(path, firestore_patch.VERSION_EXPR) + + self.assertEqual(value, "1.2.3") + + +class UrlHashExprTest(TestUtilsMixin, unittest.TestCase): + + def test_matches_sha256(self): + path = self.create_temp_file_with_line("URL_HASH SHA256=abc123def456") + + value = firestore_patch.load_value(path, firestore_patch.URL_HASH_EXPR) + + self.assertEqual(value, "SHA256=abc123def456") + + def test_ignores_whitespace(self): + path = self.create_temp_file_with_line(" URL_HASH abc123def456 ") + + value = firestore_patch.load_value(path, firestore_patch.URL_HASH_EXPR) + + self.assertEqual(value, "abc123def456") + + def test_case_insensitive(self): + path = self.create_temp_file_with_line("UrL_hAsH Sha256=abc123def456") + + value = firestore_patch.load_value(path, firestore_patch.URL_HASH_EXPR) + + self.assertEqual(value, "Sha256=abc123def456") + + +class LoadValueTest(TestUtilsMixin, unittest.TestCase): + + def test_loads_the_value(self): + path = self.create_temp_file_with_line("aaa1234ccc") + expr = re.compile(r"\D+(\d+)\D+") + + value = firestore_patch.load_value(path, expr) + + self.assertEqual(value, "1234") + + def test_loads_the_value_ignoring_non_matching_lines(self): + path = self.create_temp_file_with_lines([ + "blah", + "blah", + "aaa1234cccc", + "blah", + "blah", + ]) + expr = re.compile(r"\D+(\d+)\D+") + + value = firestore_patch.load_value(path, expr) + + self.assertEqual(value, "1234") + + def test_raises_error_if_no_matching_line_found(self): + path = self.create_temp_file_with_lines([ + "blah", + "blah", + "blah", + "blah", + ]) + expr = re.compile(r"\D+(\d+)\D+") + + with self.assertRaises(firestore_patch.RegexMatchError) as cm: + firestore_patch.load_value(path, expr) + + self.assertIn("no line matching", str(cm.exception).lower()) + self.assertIn(expr.pattern, str(cm.exception)) + self.assertIn(str(path), str(cm.exception)) + + def test_raises_error_if_multiple_matching_lines_found(self): + lines = ["blah"] * 100 + lines.append("aaa123bbb") + lines.append("ccc456ddd") + path = self.create_temp_file_with_lines(lines) + expr = re.compile(r"\D+(\d+)\D+") + + with self.assertRaises(firestore_patch.RegexMatchError) as cm: + firestore_patch.load_value(path, expr) + + self.assertIn("multiple lines matching", str(cm.exception).lower()) + self.assertIn(str(path), str(cm.exception)) + self.assertIn(expr.pattern, str(cm.exception)) + self.assertIn("line 101", str(cm.exception)) + self.assertIn("line 102", str(cm.exception)) + self.assertIn("123", str(cm.exception)) + self.assertIn("456", str(cm.exception)) + + +class SaveValueTest(TestUtilsMixin, unittest.TestCase): + + def test_saves_the_value(self): + path = self.create_temp_file_with_line("aaa1234ccc") + expr = re.compile(r"\D+(\d+)\D+") + + firestore_patch.set_value(path, expr, "9876") + + new_value = firestore_patch.load_value(path, expr) + self.assertEqual(new_value, "9876") + + def test_saves_the_value_ignoring_non_matching_lines(self): + path = self.create_temp_file_with_lines([ + "blah", + "blah", + "aaa1234cccc", + "blah", + "blah", + ]) + expr = re.compile(r"\D+(\d+)\D+") + file_contents_before = path.read_text(encoding="utf8") + + firestore_patch.set_value(path, expr, "9876") + + file_contents_after = path.read_text(encoding="utf8") + self.assertEqual( + file_contents_after, + file_contents_before.replace("1234", "9876"), + ) + + def test_raises_error_if_no_matching_line_found(self): + path = self.create_temp_file_with_lines([ + "blah", + "blah", + "blah", + "blah", + ]) + expr = re.compile(r"\D+(\d+)\D+") + + with self.assertRaises(firestore_patch.RegexMatchError) as cm: + firestore_patch.set_value(path, expr, "") + + self.assertIn("no line matching", str(cm.exception).lower()) + self.assertIn(expr.pattern, str(cm.exception)) + self.assertIn(str(path), str(cm.exception)) + + def test_raises_error_if_multiple_matching_lines_found(self): + lines = ["blah"] * 100 + lines.append("aaa123bbb") + lines.append("ccc456ddd") + path = self.create_temp_file_with_lines(lines) + expr = re.compile(r"\D+(\d+)\D+") + + with self.assertRaises(firestore_patch.RegexMatchError) as cm: + firestore_patch.set_value(path, expr, "") + + self.assertIn("multiple lines matching", str(cm.exception).lower()) + self.assertIn(str(path), str(cm.exception)) + self.assertIn(expr.pattern, str(cm.exception)) + self.assertIn("line 101", str(cm.exception)) + self.assertIn("line 102", str(cm.exception)) + self.assertIn("123", str(cm.exception)) + self.assertIn("456", str(cm.exception)) + + +if __name__ == "__main__": + unittest.main() diff --git a/cmake/external/firestore_snappy.patch.txt b/cmake/external/firestore_snappy.patch.txt deleted file mode 100644 index 317ecc6823..0000000000 --- a/cmake/external/firestore_snappy.patch.txt +++ /dev/null @@ -1,619 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 29458bf13..7be37691d 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -227,6 +227,12 @@ if(NOT ZLIB_FOUND) - endif() - - -+# Snappy -+set(SNAPPY_BUILD_TESTS OFF CACHE BOOL "Firestore disabled") -+set(SNAPPY_BUILD_BENCHMARKS OFF CACHE BOOL "Firestore disabled") -+add_external_subdirectory(snappy) -+firebase_ios_add_alias(Snappy::Snappy snappy) -+ - # LevelDB - set(LEVELDB_BUILD_TESTS OFF CACHE BOOL "Firestore disabled") - set(LEVELDB_BUILD_BENCHMARKS OFF CACHE BOOL "Firestore disabled") -diff --git a/cmake/external/CMakeLists.txt b/cmake/external/CMakeLists.txt -index 2179633a8..c1de37b6d 100644 ---- a/cmake/external/CMakeLists.txt -+++ b/cmake/external/CMakeLists.txt -@@ -35,6 +35,7 @@ include(c-ares) - include(googletest) - include(GoogleUtilities) - include(grpc) -+include(snappy) - include(leveldb) - include(libfuzzer) - include(nanopb) -diff --git a/cmake/external/leveldb.cmake b/cmake/external/leveldb.cmake -index b71a77535..2556d7041 100644 ---- a/cmake/external/leveldb.cmake -+++ b/cmake/external/leveldb.cmake -@@ -13,20 +13,27 @@ - # limitations under the License. - - include(ExternalProject) -+include(FindPythonInterp) - - if(TARGET leveldb) - return() - endif() - --set(version 1.22) -+set(version 1.23) -+ -+ExternalProject_Get_property(snappy SOURCE_DIR) -+set(snappy_source_dir "${SOURCE_DIR}") -+ExternalProject_Get_property(snappy BINARY_DIR) -+set(snappy_binary_dir "${BINARY_DIR}") - - ExternalProject_Add( - leveldb - -+ DEPENDS snappy -+ - DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} - DOWNLOAD_NAME leveldb-${version}.tar.gz - URL https://github.com/google/leveldb/archive/${version}.tar.gz -- URL_HASH SHA256=55423cac9e3306f4a9502c738a001e4a339d1a38ffbee7572d4a07d5d63949b2 - - PREFIX ${PROJECT_BINARY_DIR} - -@@ -34,6 +41,7 @@ ExternalProject_Add( - BUILD_COMMAND "" - INSTALL_COMMAND "" - TEST_COMMAND "" -+ PATCH_COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/leveldb_patch.py --snappy-source-dir ${snappy_source_dir} --snappy-binary-dir ${snappy_binary_dir} - - HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" - ) -diff --git a/cmake/external/leveldb_patch.py b/cmake/external/leveldb_patch.py -new file mode 100644 -index 000000000..51a62d54a ---- /dev/null -+++ b/cmake/external/leveldb_patch.py -@@ -0,0 +1,144 @@ -+# Copyright 2022 Google LLC -+# -+# Licensed under the Apache License, Version 2.0 (the "License"); -+# you may not use this file except in compliance with the License. -+# You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+ -+""" -+Modify the CMakeLists.txt from LevelDb to staticly link Snappy compression -+support. -+""" -+ -+import argparse -+import dataclasses -+import os -+import pathlib -+from typing import Iterable, Sequence -+ -+ -+def main() -> None: -+ arg_parser = argparse.ArgumentParser() -+ arg_parser.add_argument("--snappy-source-dir", required=True) -+ arg_parser.add_argument("--snappy-binary-dir", required=True) -+ parsed_args = arg_parser.parse_args() -+ del arg_parser -+ snappy_source_dir = pathlib.Path(parsed_args.snappy_source_dir) -+ snappy_binary_dir = pathlib.Path(parsed_args.snappy_binary_dir) -+ del parsed_args -+ -+ cmakelists_txt_file = pathlib.Path("CMakeLists.txt") -+ with cmakelists_txt_file.open("rt", encoding="utf8") as f: -+ lines = tuple(f) -+ -+ patcher = CMakeListsPatcher( -+ lines, -+ os.path.abspath(__file__), -+ snappy_source_dir, -+ snappy_binary_dir, -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ with cmakelists_txt_file.open("wt", encoding="utf8") as f: -+ f.writelines(patched_lines) -+ -+ -+@dataclasses.dataclass(frozen=True) -+class LineComponents: -+ full: str -+ indent: str -+ line: str -+ eol: str -+ -+ -+class CMakeListsPatcher: -+ -+ SNAPPY_DETECT_LINE = \ -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""" -+ SNAPPY_INCLUDE_LINE = \ -+ "target_include_directories(leveldb" -+ SNAPPY_LINK_LINE = \ -+ "target_link_libraries(leveldb snappy)" -+ -+ def __init__( -+ self, -+ lines: Sequence[str], -+ script_name: str, -+ snappy_source_dir: pathlib.Path, -+ snappy_binary_dir: pathlib.Path) -> None: -+ self.i = 0 -+ self.lines = lines -+ self.script_name = script_name -+ self.snappy_source_dir_str = snappy_source_dir.as_posix() -+ self.snappy_binary_dir_str = snappy_binary_dir.as_posix() -+ -+ def patch(self) -> Iterable[str]: -+ while self.i < len(self.lines): -+ full_line = self.lines[self.i] -+ line = self._split_line(full_line) -+ self.i += 1 -+ -+ if line.line == self.SNAPPY_DETECT_LINE: -+ yield from self._on_snappy_detect_line(line) -+ elif line.line == self.SNAPPY_INCLUDE_LINE: -+ yield full_line -+ yield from self._on_leveldb_include_start() -+ elif line.line == self.SNAPPY_LINK_LINE: -+ yield from self._on_leveldb_snappy_link_line(line) -+ else: -+ yield full_line -+ -+ def _begin_mod_line(self, mod_name: str) -> str: -+ return f"# BEGIN: {mod_name} modification by {self.script_name}" -+ -+ def _end_mod_line(self, mod_name: str) -> str: -+ return f"# END: {mod_name} modification by {self.script_name}" -+ -+ def _on_snappy_detect_line(self, line: LineComponents) -> Iterable[str]: -+ yield self._begin_mod_line("snappy_detect_line") + line.eol -+ yield line.indent + "# " + line.line + line.eol -+ yield line.indent + """set(HAVE_SNAPPY ON CACHE BOOL "")""" + line.eol -+ yield self._end_mod_line("snappy_detect_line") + line.eol -+ -+ def _on_leveldb_include_start(self) -> Iterable[str]: -+ line1 = self._split_line(self.lines[self.i]) -+ line2 = self._split_line(self.lines[self.i + 1]) -+ begin_mod_line = self._begin_mod_line("leveldb_include_start") -+ -+ if line1.line == begin_mod_line: -+ return -+ -+ yield begin_mod_line + line1.eol -+ yield line1.indent + "PRIVATE" + line1.eol -+ yield line2.indent + self.snappy_source_dir_str + line2.eol -+ yield line2.indent + self.snappy_binary_dir_str + line2.eol -+ yield self._end_mod_line("leveldb_include_start") + line1.eol -+ -+ def _on_leveldb_snappy_link_line(self, line: LineComponents) -> Iterable[str]: -+ yield self._begin_mod_line("leveldb_snappy_link_line") + line.eol -+ yield line.indent + "# " + line.line + line.eol -+ yield line.indent + f"target_link_libraries(leveldb Snappy::Snappy)" + line.eol -+ yield self._end_mod_line("leveldb_snappy_link_line") + line.eol -+ -+ def _split_line(self, line: str) -> LineComponents: -+ line_rstripped = line.rstrip() -+ eol = line[len(line_rstripped):] -+ line_stripped = line_rstripped.strip() -+ indent = line_rstripped[:len(line_rstripped) - len(line_stripped)] -+ return LineComponents(full=line, indent=indent, line=line_stripped, eol=eol) -+ -+ -+class LeveDbPatchException(Exception): -+ pass -+ -+ -+if __name__ == "__main__": -+ main() -diff --git a/cmake/external/leveldb_patch_test.py b/cmake/external/leveldb_patch_test.py -new file mode 100644 -index 000000000..b1d62526b ---- /dev/null -+++ b/cmake/external/leveldb_patch_test.py -@@ -0,0 +1,328 @@ -+# Copyright 2022 Google LLC -+# -+# Licensed under the Apache License, Version 2.0 (the "License"); -+# you may not use this file except in compliance with the License. -+# You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+ -+import leveldb_patch -+import pathlib -+import unittest -+ -+ -+class CMakeListsPatcherTest(unittest.TestCase): -+ -+ def setUp(self): -+ super().setUp() -+ self.sample_snappy_source_dir = pathlib.Path("a/b/snappy_source_dir") -+ self.sample_snappy_binary_dir = pathlib.Path("a/b/snappy_binary_dir") -+ -+ def test_snappy_detect_line_is_commented_and_replaced(self): -+ lines = ( -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ "MyCoolScript", -+ self.sample_snappy_source_dir, -+ self.sample_snappy_binary_dir, -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: snappy_detect_line modification by MyCoolScript", -+ """# check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ """set(HAVE_SNAPPY ON CACHE BOOL "")""", -+ "# END: snappy_detect_line modification by MyCoolScript", -+ ]) -+ -+ def test_snappy_detect_line_has_indent_and_eol_preserved(self): -+ lines = ( -+ """ check_library_exists(snappy snappy_compress "" HAVE_SNAPPY) \n""", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ "MyCoolScript", -+ self.sample_snappy_source_dir, -+ self.sample_snappy_binary_dir, -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: snappy_detect_line modification by MyCoolScript \n", -+ """ # check_library_exists(snappy snappy_compress "" HAVE_SNAPPY) \n""", -+ """ set(HAVE_SNAPPY ON CACHE BOOL "") \n""", -+ "# END: snappy_detect_line modification by MyCoolScript \n", -+ ]) -+ -+ def test_snappy_detect_line_does_not_affect_surrounding_lines(self): -+ lines = ( -+ "aaa", -+ "bbb", -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ "ccc", -+ "ddd", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ "MyCoolScript", -+ self.sample_snappy_source_dir, -+ self.sample_snappy_binary_dir, -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "aaa", -+ "bbb", -+ "# BEGIN: snappy_detect_line modification by MyCoolScript", -+ """# check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ """set(HAVE_SNAPPY ON CACHE BOOL "")""", -+ "# END: snappy_detect_line modification by MyCoolScript", -+ "ccc", -+ "ddd", -+ ]) -+ -+ def test_snappy_include_is_amended(self): -+ lines = ( -+ "target_include_directories(leveldb", -+ "PUBLIC", -+ "path1", -+ "path2", -+ ")", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "target_include_directories(leveldb", -+ "# BEGIN: leveldb_include_start modification by MyCoolSript", -+ "PRIVATE", -+ "a/b", -+ "c/d", -+ "# END: leveldb_include_start modification by MyCoolSript", -+ "PUBLIC", -+ "path1", -+ "path2", -+ ")", -+ ]) -+ -+ def test_snappy_include_lines_adopt_indenting_and_eol_convention(self): -+ lines = ( -+ "target_include_directories(leveldb\n", -+ " PUBLIC \n", -+ " path1 \n", -+ " path2 \n", -+ ")\n", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "target_include_directories(leveldb\n", -+ "# BEGIN: leveldb_include_start modification by MyCoolSript \n", -+ " PRIVATE \n", -+ " a/b \n", -+ " c/d \n", -+ "# END: leveldb_include_start modification by MyCoolSript \n", -+ " PUBLIC \n", -+ " path1 \n", -+ " path2 \n", -+ ")\n", -+ ]) -+ -+ def test_snappy_include_line_does_not_affect_surrounding_lines(self): -+ lines = ( -+ "aaa", -+ "bbb", -+ "target_include_directories(leveldb", -+ "PUBLIC", -+ "path1", -+ "path2", -+ ")", -+ "ccc", -+ "ddd", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "aaa", -+ "bbb", -+ "target_include_directories(leveldb", -+ "# BEGIN: leveldb_include_start modification by MyCoolSript", -+ "PRIVATE", -+ "a/b", -+ "c/d", -+ "# END: leveldb_include_start modification by MyCoolSript", -+ "PUBLIC", -+ "path1", -+ "path2", -+ ")", -+ "ccc", -+ "ddd", -+ ]) -+ -+ def test_leveldb_snappy_link_line_is_commented_and_replaced(self): -+ lines = ( -+ "target_link_libraries(leveldb snappy)", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript", -+ "# target_link_libraries(leveldb snappy)", -+ "target_link_libraries(leveldb Snappy::Snappy)", -+ "# END: leveldb_snappy_link_line modification by MyCoolSript", -+ ]) -+ -+ def test_leveldb_snappy_link_line_has_indent_and_eol_preserved(self): -+ lines = ( -+ " target_link_libraries(leveldb snappy) \n", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript \n", -+ " # target_link_libraries(leveldb snappy) \n", -+ " target_link_libraries(leveldb Snappy::Snappy) \n", -+ "# END: leveldb_snappy_link_line modification by MyCoolSript \n", -+ ]) -+ -+ def test_leveldb_snappy_link_line_does_not_affect_surrounding_lines(self): -+ lines = ( -+ "aaa", -+ "bbb", -+ "target_link_libraries(leveldb snappy)", -+ "ccc", -+ "ddd", -+ ) -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "aaa", -+ "bbb", -+ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript", -+ "# target_link_libraries(leveldb snappy)", -+ "target_link_libraries(leveldb Snappy::Snappy)", -+ "# END: leveldb_snappy_link_line modification by MyCoolSript", -+ "ccc", -+ "ddd", -+ ]) -+ -+ def test_all_patches_combined(self): -+ lines = ( -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ "target_include_directories(leveldb", -+ "PUBLIC", -+ "path1", -+ ")", -+ "target_link_libraries(leveldb snappy)", -+ ) -+ -+ patcher = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ patched_lines = tuple(patcher.patch()) -+ -+ self.assertSequenceEqual(patched_lines, [ -+ "# BEGIN: snappy_detect_line modification by MyCoolSript", -+ """# check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)""", -+ """set(HAVE_SNAPPY ON CACHE BOOL "")""", -+ "# END: snappy_detect_line modification by MyCoolSript", -+ "target_include_directories(leveldb", -+ "# BEGIN: leveldb_include_start modification by MyCoolSript", -+ "PRIVATE", -+ "a/b", -+ "c/d", -+ "# END: leveldb_include_start modification by MyCoolSript", -+ "PUBLIC", -+ "path1", -+ ")", -+ "# BEGIN: leveldb_snappy_link_line modification by MyCoolSript", -+ "# target_link_libraries(leveldb snappy)", -+ "target_link_libraries(leveldb Snappy::Snappy)", -+ "# END: leveldb_snappy_link_line modification by MyCoolSript", -+ ]) -+ -+ def test_idempotence(self): -+ lines = ( -+ """check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)\n""", -+ "target_include_directories(leveldb", -+ "PUBLIC", -+ "path1", -+ ")", -+ "target_link_libraries(leveldb snappy)", -+ ) -+ -+ patcher1 = leveldb_patch.CMakeListsPatcher( -+ lines, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ patched_lines1 = tuple(patcher1.patch()) -+ patcher2 = leveldb_patch.CMakeListsPatcher( -+ patched_lines1, -+ script_name="MyCoolSript", -+ snappy_source_dir=pathlib.Path("a/b"), -+ snappy_binary_dir=pathlib.Path("c/d"), -+ ) -+ patched_lines2 = tuple(patcher2.patch()) -+ -+ self.assertSequenceEqual(patched_lines1, patched_lines2) -+ -+ -+if __name__ == "__main__": -+ unittest.main() -diff --git a/cmake/external/snappy.cmake b/cmake/external/snappy.cmake -new file mode 100644 -index 000000000..9f25c03d0 ---- /dev/null -+++ b/cmake/external/snappy.cmake -@@ -0,0 +1,40 @@ -+# Copyright 2022 Google LLC -+# -+# Licensed under the Apache License, Version 2.0 (the "License"); -+# you may not use this file except in compliance with the License. -+# You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+ -+include(ExternalProject) -+ -+if(TARGET snappy) -+ return() -+endif() -+ -+set(version 1.1.9) -+ -+ExternalProject_Add( -+ snappy -+ -+ DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} -+ DOWNLOAD_NAME snappy-${version}.tar.gz -+ URL https://github.com/google/snappy/archive/refs/tags/${version}.tar.gz -+ URL_HASH SHA256=75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7 -+ -+ PREFIX ${PROJECT_BINARY_DIR} -+ -+ CONFIGURE_COMMAND "" -+ BUILD_COMMAND "" -+ INSTALL_COMMAND "" -+ TEST_COMMAND "" -+ PATCH_COMMAND patch -Np1 -i ${CMAKE_CURRENT_LIST_DIR}/snappy.patch -+ -+ HTTP_HEADER "${EXTERNAL_PROJECT_HTTP_HEADER}" -+) -diff --git a/cmake/external/snappy.patch b/cmake/external/snappy.patch -new file mode 100644 -index 000000000..28bfb0837 ---- /dev/null -+++ b/cmake/external/snappy.patch -@@ -0,0 +1,12 @@ -+diff -Naur snappy/snappy.cc snappy_patched/snappy.cc -+--- snappy/snappy.cc 2022-04-12 20:44:55.000000000 -0400 -++++ snappy_patched/snappy.cc 2022-04-12 20:47:05.000000000 -0400 -+@@ -1014,7 +1014,7 @@ -+ } -+ -+ SNAPPY_ATTRIBUTE_ALWAYS_INLINE -+-size_t AdvanceToNextTag(const uint8_t** ip_p, size_t* tag) { -++inline size_t AdvanceToNextTag(const uint8_t** ip_p, size_t* tag) { -+ const uint8_t*& ip = *ip_p; -+ // This section is crucial for the throughput of the decompression loop. -+ // The latency of an iteration is fundamentally constrained by the diff --git a/cmake/external/leveldb.cmake b/cmake/external/leveldb.cmake index 18970659a4..a8a154bb4e 100644 --- a/cmake/external/leveldb.cmake +++ b/cmake/external/leveldb.cmake @@ -26,6 +26,7 @@ ExternalProject_Add( DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} DOWNLOAD_NAME leveldb-${version}.tar.gz URL https://github.com/google/leveldb/archive/${version}.tar.gz + URL_HASH SHA256=9a37f8a6174f09bd622bc723b55881dc541cd50747cbd08831c2a82d620f6d76 PREFIX ${PROJECT_BINARY_DIR} From ae416848250afba3fb7dc476c5c7a314cf3b1364 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 11:37:42 -0400 Subject: [PATCH 06/47] firestore.cmake: pin to the HEAD commit of https://github.com/firebase/firebase-ios-sdk/pull/9838, which adds TransactionOptions --- cmake/external/firestore.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index c9f8f3c020..5177224cf9 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -36,7 +36,9 @@ function(GetReleasedDep) firestore DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} - URL https://github.com/firebase/firebase-ios-sdk/archive/${version}.tar.gz + # Pin to the HEAD commit of https://github.com/firebase/firebase-cpp-sdk/pull/932 + GIT_REPOSITORY https://github.com/firebase/firebase-ios-sdk.git + GIT_TAG 0fe625cf72254bfb8b0a899dd2c006836fafe475 PREFIX ${PROJECT_BINARY_DIR} From 20240d6850dbac8caf2714258dc48ff241542329 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 12:29:36 -0400 Subject: [PATCH 07/47] transaction_options.h: skeleton added --- firestore/CMakeLists.txt | 1 + .../integration_test_internal/CMakeLists.txt | 1 + .../src/transaction_options_test.cc | 50 +++++++++++++++++++ firestore/src/common/transaction_options.cc | 34 +++++++++++++ firestore/src/include/firebase/firestore.h | 1 + .../firebase/firestore/transaction_options.h | 40 +++++++++++++++ 6 files changed, 127 insertions(+) create mode 100644 firestore/integration_test_internal/src/transaction_options_test.cc create mode 100644 firestore/src/common/transaction_options.cc create mode 100644 firestore/src/include/firebase/firestore/transaction_options.h diff --git a/firestore/CMakeLists.txt b/firestore/CMakeLists.txt index 59e5813ab3..e989317537 100644 --- a/firestore/CMakeLists.txt +++ b/firestore/CMakeLists.txt @@ -49,6 +49,7 @@ set(common_SRCS src/common/to_string.h src/common/type_mapping.h src/common/transaction.cc + src/common/transaction_options.cc src/common/util.cc src/common/util.h src/common/write_batch.cc diff --git a/firestore/integration_test_internal/CMakeLists.txt b/firestore/integration_test_internal/CMakeLists.txt index 4e03212053..664236b946 100644 --- a/firestore/integration_test_internal/CMakeLists.txt +++ b/firestore/integration_test_internal/CMakeLists.txt @@ -100,6 +100,7 @@ set(FIREBASE_INTEGRATION_TEST_PORTABLE_TEST_SRCS src/smoke_test.cc src/source_test.cc src/transaction_test.cc + src/transaction_options_test.cc src/type_test.cc src/validation_test.cc src/write_batch_test.cc diff --git a/firestore/integration_test_internal/src/transaction_options_test.cc b/firestore/integration_test_internal/src/transaction_options_test.cc new file mode 100644 index 0000000000..fd48fb9e2a --- /dev/null +++ b/firestore/integration_test_internal/src/transaction_options_test.cc @@ -0,0 +1,50 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "firebase/firestore.h" +#include "gtest/gtest.h" + +namespace firebase { +namespace firestore { +namespace { + +TEST(TransactionOptionsTest, DefaultConstructor) { + TransactionOptions options; + EXPECT_EQ(options.max_attempts(), 5); +} + +TEST(TransactionOptionsTest, SetMaxAttemptsSetsValidValues) { + TransactionOptions options; + options.set_max_attempts(10); + EXPECT_EQ(options.max_attempts(), 10); + options.set_max_attempts(1); + EXPECT_EQ(options.max_attempts(), 1); + options.set_max_attempts(2); + EXPECT_EQ(options.max_attempts(), 2); + options.set_max_attempts(INT32_MAX); + EXPECT_EQ(options.max_attempts(), INT32_MAX); +} + +TEST(TransactionOptionsTest, SetMaxAttemptsThrowsOnInvalidValues) { + TransactionOptions options; + EXPECT_ANY_THROW(options.set_max_attempts(0)); + EXPECT_ANY_THROW(options.set_max_attempts(-1)); + EXPECT_ANY_THROW(options.set_max_attempts(INT32_MIN)); +} + +} // namespace +} // namespace firestore +} // namespace firebase diff --git a/firestore/src/common/transaction_options.cc b/firestore/src/common/transaction_options.cc new file mode 100644 index 0000000000..dab397ca95 --- /dev/null +++ b/firestore/src/common/transaction_options.cc @@ -0,0 +1,34 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "firestore/src/include/firebase/firestore/transaction_options.h" + +#include +#include + +#include "firestore/src/common/hard_assert_common.h" + +namespace firebase { +namespace firestore { + +void TransactionOptions::set_max_attempts(int32_t max_attempts) { + SIMPLE_HARD_ASSERT(max_attempts > 0, + "invalid max_attempts: " + std::to_string(max_attempts)); + max_attempts_ = max_attempts; +} + +} // namespace firestore +} // namespace firebase diff --git a/firestore/src/include/firebase/firestore.h b/firestore/src/include/firebase/firestore.h index 8ac64fda63..c02ed21c5d 100644 --- a/firestore/src/include/firebase/firestore.h +++ b/firestore/src/include/firebase/firestore.h @@ -47,6 +47,7 @@ #include "firebase/firestore/source.h" #include "firebase/firestore/timestamp.h" #include "firebase/firestore/transaction.h" +#include "firebase/firestore/transaction_options.h" #include "firebase/firestore/write_batch.h" namespace firebase { diff --git a/firestore/src/include/firebase/firestore/transaction_options.h b/firestore/src/include/firebase/firestore/transaction_options.h new file mode 100644 index 0000000000..5798ac511c --- /dev/null +++ b/firestore/src/include/firebase/firestore/transaction_options.h @@ -0,0 +1,40 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_TRANSACTION_OPTIONS_H_ +#define FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_TRANSACTION_OPTIONS_H_ + +#include + +namespace firebase { +namespace firestore { + +class TransactionOptions final { + public: + TransactionOptions() = default; + + int32_t max_attempts() const { return max_attempts_; } + + void set_max_attempts(int32_t max_attempts); + + private: + int32_t max_attempts_ = 5; +}; + +} // namespace firestore +} // namespace firebase + +#endif // FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_TRANSACTION_OPTIONS_H_ From de41abab3f01791b2091c0a24adccf95809bee9c Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 13:04:07 -0400 Subject: [PATCH 08/47] transaction_options_test.cc: add tests for copy and move constructor and assignment operator. --- .../src/transaction_options_test.cc | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/firestore/integration_test_internal/src/transaction_options_test.cc b/firestore/integration_test_internal/src/transaction_options_test.cc index fd48fb9e2a..d4ef2c7768 100644 --- a/firestore/integration_test_internal/src/transaction_options_test.cc +++ b/firestore/integration_test_internal/src/transaction_options_test.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include "firebase/firestore.h" #include "gtest/gtest.h" @@ -26,6 +28,48 @@ TEST(TransactionOptionsTest, DefaultConstructor) { EXPECT_EQ(options.max_attempts(), 5); } +TEST(TransactionOptionsTest, CopyConstructor) { + TransactionOptions options; + options.set_max_attempts(99); + + TransactionOptions copied_options(options); + + EXPECT_EQ(options.max_attempts(), 99); + EXPECT_EQ(copied_options.max_attempts(), 99); +} + +TEST(TransactionOptionsTest, CopyAssignmentOperator) { + TransactionOptions options; + options.set_max_attempts(99); + TransactionOptions options_copy_dest; + options_copy_dest.set_max_attempts(333); + + options_copy_dest = options; + + EXPECT_EQ(options.max_attempts(), 99); + EXPECT_EQ(options_copy_dest.max_attempts(), 99); +} + +TEST(TransactionOptionsTest, MoveConstructor) { + TransactionOptions options; + options.set_max_attempts(99); + + TransactionOptions moved_options(std::move(options)); + + EXPECT_EQ(moved_options.max_attempts(), 99); +} + +TEST(TransactionOptionsTest, MoveAssignmentOperator) { + TransactionOptions options; + options.set_max_attempts(99); + TransactionOptions options_move_dest; + options_move_dest.set_max_attempts(333); + + options_move_dest = std::move(options); + + EXPECT_EQ(options_move_dest.max_attempts(), 99); +} + TEST(TransactionOptionsTest, SetMaxAttemptsSetsValidValues) { TransactionOptions options; options.set_max_attempts(10); From 4d2024346c41427bef532a7d33d0c8c885227d06 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 13:04:56 -0400 Subject: [PATCH 09/47] transaction_options.cc: add ToString() and << std::ostream operator. --- .../src/transaction_options_test.cc | 21 +++++++++++++++++++ firestore/src/common/transaction_options.cc | 9 ++++++++ .../firebase/firestore/transaction_options.h | 18 ++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/firestore/integration_test_internal/src/transaction_options_test.cc b/firestore/integration_test_internal/src/transaction_options_test.cc index d4ef2c7768..78a11df09e 100644 --- a/firestore/integration_test_internal/src/transaction_options_test.cc +++ b/firestore/integration_test_internal/src/transaction_options_test.cc @@ -15,6 +15,7 @@ */ #include +#include #include "firebase/firestore.h" #include "gtest/gtest.h" @@ -89,6 +90,26 @@ TEST(TransactionOptionsTest, SetMaxAttemptsThrowsOnInvalidValues) { EXPECT_ANY_THROW(options.set_max_attempts(INT32_MIN)); } +TEST(TransactionOptionsTest, ToString) { + TransactionOptions options; + options.set_max_attempts(42); + + const std::string to_string_result = options.ToString(); + + EXPECT_EQ(to_string_result, "TransactionOptions(max_attempts=42)"); +} + +TEST(TransactionOptionsTest, RightShiftOperatorToOutputStream) { + TransactionOptions options; + options.set_max_attempts(42); + const std::string expected_str = options.ToString(); + std::ostringstream ss; + + ss << options; + + EXPECT_EQ(ss.str(), expected_str); +} + } // namespace } // namespace firestore } // namespace firebase diff --git a/firestore/src/common/transaction_options.cc b/firestore/src/common/transaction_options.cc index dab397ca95..be422da7c1 100644 --- a/firestore/src/common/transaction_options.cc +++ b/firestore/src/common/transaction_options.cc @@ -30,5 +30,14 @@ void TransactionOptions::set_max_attempts(int32_t max_attempts) { max_attempts_ = max_attempts; } +std::string TransactionOptions::ToString() const { + return std::string("TransactionOptions(max_attempts=") + std::to_string(max_attempts()) + ")"; +} + +std::ostream& operator<<(std::ostream& out, const TransactionOptions& options) { + return out << options.ToString(); +} + + } // namespace firestore } // namespace firebase diff --git a/firestore/src/include/firebase/firestore/transaction_options.h b/firestore/src/include/firebase/firestore/transaction_options.h index 5798ac511c..943b7333e9 100644 --- a/firestore/src/include/firebase/firestore/transaction_options.h +++ b/firestore/src/include/firebase/firestore/transaction_options.h @@ -18,6 +18,8 @@ #define FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_TRANSACTION_OPTIONS_H_ #include +#include +#include namespace firebase { namespace firestore { @@ -30,6 +32,22 @@ class TransactionOptions final { void set_max_attempts(int32_t max_attempts); + /** + * Returns a string representation of this `TransactionOptions` object for + * logging/debugging purposes. + * + * @note the exact string representation is unspecified and subject to + * change; don't rely on the format of the string. + */ + std::string ToString() const; + + /** + * Outputs the string representation of this `TransactionOptions` object to + * the given stream. + * + * @see `ToString()` for comments on the representation format. + */ + friend std::ostream& operator<<(std::ostream&, const TransactionOptions&); private: int32_t max_attempts_ = 5; }; From 3934e9e9fec84c71a673ec3d474b292c51048002 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 13:16:30 -0400 Subject: [PATCH 10/47] transaction_options.h: add == and != operator overloads --- .../src/transaction_options_test.cc | 44 +++++++++++++++++++ firestore/src/common/transaction_options.cc | 3 ++ .../firebase/firestore/transaction_options.h | 8 ++++ 3 files changed, 55 insertions(+) diff --git a/firestore/integration_test_internal/src/transaction_options_test.cc b/firestore/integration_test_internal/src/transaction_options_test.cc index 78a11df09e..36c190ebcc 100644 --- a/firestore/integration_test_internal/src/transaction_options_test.cc +++ b/firestore/integration_test_internal/src/transaction_options_test.cc @@ -110,6 +110,50 @@ TEST(TransactionOptionsTest, RightShiftOperatorToOutputStream) { EXPECT_EQ(ss.str(), expected_str); } +TEST(TransactionOptionsTest, EqualsOperator) { + TransactionOptions default_options1; + TransactionOptions default_options2; + TransactionOptions options1a; + options1a.set_max_attempts(1); + TransactionOptions options1b; + options1b.set_max_attempts(1); + TransactionOptions options2a; + options2a.set_max_attempts(99); + TransactionOptions options2b; + options2b.set_max_attempts(99); + + EXPECT_TRUE(default_options1 == default_options1); + EXPECT_TRUE(default_options1 == default_options2); + EXPECT_TRUE(options1a == options1b); + EXPECT_TRUE(options2a == options2b); + + EXPECT_FALSE(options1a == options2a); + EXPECT_FALSE(options1a == default_options1); + EXPECT_FALSE(options2a == default_options1); +} + +TEST(TransactionOptionsTest, NotEqualsOperator) { + TransactionOptions default_options1; + TransactionOptions default_options2; + TransactionOptions options1a; + options1a.set_max_attempts(1); + TransactionOptions options1b; + options1b.set_max_attempts(1); + TransactionOptions options2a; + options2a.set_max_attempts(99); + TransactionOptions options2b; + options2b.set_max_attempts(99); + + EXPECT_FALSE(default_options1 != default_options1); + EXPECT_FALSE(default_options1 != default_options2); + EXPECT_FALSE(options1a != options1b); + EXPECT_FALSE(options2a != options2b); + + EXPECT_TRUE(options1a != options2a); + EXPECT_TRUE(options1a != default_options1); + EXPECT_TRUE(options2a != default_options1); +} + } // namespace } // namespace firestore } // namespace firebase diff --git a/firestore/src/common/transaction_options.cc b/firestore/src/common/transaction_options.cc index be422da7c1..4e9829c7c2 100644 --- a/firestore/src/common/transaction_options.cc +++ b/firestore/src/common/transaction_options.cc @@ -38,6 +38,9 @@ std::ostream& operator<<(std::ostream& out, const TransactionOptions& options) { return out << options.ToString(); } +bool operator==(const TransactionOptions& lhs, const TransactionOptions& rhs) { + return lhs.max_attempts() == rhs.max_attempts(); +} } // namespace firestore } // namespace firebase diff --git a/firestore/src/include/firebase/firestore/transaction_options.h b/firestore/src/include/firebase/firestore/transaction_options.h index 943b7333e9..badb6c7030 100644 --- a/firestore/src/include/firebase/firestore/transaction_options.h +++ b/firestore/src/include/firebase/firestore/transaction_options.h @@ -52,6 +52,14 @@ class TransactionOptions final { int32_t max_attempts_ = 5; }; +/** Compares two `TransactionOptions` objects for equality. */ +bool operator==(const TransactionOptions&, const TransactionOptions&); + +/** Compares two `TransactionOptions` objects for inequality. */ +inline bool operator!=(const TransactionOptions& lhs, const TransactionOptions& rhs) { + return !(lhs == rhs); +} + } // namespace firestore } // namespace firebase From 1240f7ee550739b8d3dc0c61f1fbf54d7f4bdbe9 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 15:13:05 -0400 Subject: [PATCH 11/47] transaction_options.h: add doxygen comments --- .../firebase/firestore/transaction_options.h | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/firestore/src/include/firebase/firestore/transaction_options.h b/firestore/src/include/firebase/firestore/transaction_options.h index badb6c7030..93bf63d5a6 100644 --- a/firestore/src/include/firebase/firestore/transaction_options.h +++ b/firestore/src/include/firebase/firestore/transaction_options.h @@ -24,12 +24,80 @@ namespace firebase { namespace firestore { +/** + * Options to customize transaction behavior for `Firestore.runTransaction()`. + */ class TransactionOptions final { public: + + /** + * @brief Creates the default `TransactionOptions`. + */ TransactionOptions() = default; + /** + * @brief Copy constructor. + * + * This performs a deep copy, creating an independent instance. + * + * @param[in] other `TransactionOptions` to copy from. + */ + TransactionOptions(const TransactionOptions& other) = default; + + /** + * @brief Move constructor. + * + * Moving is not any more efficient than copying for `TransactionOptions` + * because this class is trivially copyable; however, future additions to this + * class may make it not trivially copyable, at which point moving would be + * more efficient than copying. After being moved from, `TransactionOptions` + * is in a valid but unspecified state. + * + * @param[in] other `TransactionOptions` to move data from. + */ + TransactionOptions(TransactionOptions&& other) = default; + + /** + * @brief Copy assignment operator. + * + * This performs a deep copy, creating an independent instance. + * + * @param[in] other `TransactionOptions` to copy from. + * + * @return Reference to the destination `TransactionOptions`. + */ + TransactionOptions& operator=(const TransactionOptions& other) = default; + + /** + * @brief Move assignment operator. + * + * Moving is not any more efficient than copying for `TransactionOptions` + * because this class is trivially copyable; however, future additions to this + * class may make it not trivially copyable, at which point moving would be + * more efficient than copying. After being moved from, `TransactionOptions` + * is in a valid but unspecified state. + * + * @param[in] other `TransactionOptions` to move data from. + * + * @return Reference to the destination `TransactionOptions`. + */ + TransactionOptions& operator=(TransactionOptions&& other) = default; + + /** + * @brief Gets the maximum number of attempts to commit, after which the transaction fails. + * + * The default value is 5. + */ int32_t max_attempts() const { return max_attempts_; } + /** + * @brief Sets the maximum number of attempts to commit, after which the transaction fails. + * + * The default value is 5. + * + * @param[in] max_attempts The maximum number of attempts; must be greater + * than zero. + */ void set_max_attempts(int32_t max_attempts); /** From 0c920be93f680568e86a5cf077f47a7d9c99205c Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 15:32:34 -0400 Subject: [PATCH 12/47] transaction_options_test.cc: add test for trivially copyable --- .../src/transaction_options_test.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/firestore/integration_test_internal/src/transaction_options_test.cc b/firestore/integration_test_internal/src/transaction_options_test.cc index 36c190ebcc..3b04883417 100644 --- a/firestore/integration_test_internal/src/transaction_options_test.cc +++ b/firestore/integration_test_internal/src/transaction_options_test.cc @@ -16,6 +16,7 @@ #include #include +#include #include "firebase/firestore.h" #include "gtest/gtest.h" @@ -24,6 +25,10 @@ namespace firebase { namespace firestore { namespace { +TEST(TransactionOptionsTest, TypeTraits) { + static_assert(std::is_trivially_copyable::value, "Update the public doxygen comments about TransactionOptions being trivially copyable in the header file if it ever changes to NOT be trivially copyable."); +} + TEST(TransactionOptionsTest, DefaultConstructor) { TransactionOptions options; EXPECT_EQ(options.max_attempts(), 5); From 57f9fa4d6d940411d2e7a1e8eadc3a0606a62729 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 15:32:48 -0400 Subject: [PATCH 13/47] transaction_options_test.cc: minor whitespace cleanup --- firestore/src/include/firebase/firestore/transaction_options.h | 1 + 1 file changed, 1 insertion(+) diff --git a/firestore/src/include/firebase/firestore/transaction_options.h b/firestore/src/include/firebase/firestore/transaction_options.h index 93bf63d5a6..3e588d97a2 100644 --- a/firestore/src/include/firebase/firestore/transaction_options.h +++ b/firestore/src/include/firebase/firestore/transaction_options.h @@ -116,6 +116,7 @@ class TransactionOptions final { * @see `ToString()` for comments on the representation format. */ friend std::ostream& operator<<(std::ostream&, const TransactionOptions&); + private: int32_t max_attempts_ = 5; }; From a030d8567ecf260a9ea863325c6712269e55c54e Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 15:38:39 -0400 Subject: [PATCH 14/47] transaction_options.cc: use SimpleThrowInvalidArgument instead of SIMPLE_HARD_ASSERT when given an invalid max_attempts --- firestore/src/common/transaction_options.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/firestore/src/common/transaction_options.cc b/firestore/src/common/transaction_options.cc index 4e9829c7c2..a4f4136015 100644 --- a/firestore/src/common/transaction_options.cc +++ b/firestore/src/common/transaction_options.cc @@ -19,14 +19,15 @@ #include #include -#include "firestore/src/common/hard_assert_common.h" +#include "firestore/src/common/exception_common.h" namespace firebase { namespace firestore { void TransactionOptions::set_max_attempts(int32_t max_attempts) { - SIMPLE_HARD_ASSERT(max_attempts > 0, - "invalid max_attempts: " + std::to_string(max_attempts)); + if (max_attempts <= 0) { + SimpleThrowInvalidArgument("invalid max_attempts: " + std::to_string(max_attempts)); + } max_attempts_ = max_attempts; } From 2608afc1af6bf54cc771feb32e14c2d5002115dd Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 15:44:08 -0400 Subject: [PATCH 15/47] firestore.h: add RunTransaction() overload that takes TransactionOptions --- firestore/src/common/firestore.cc | 6 +++++- firestore/src/include/firebase/firestore.h | 15 +++++++++++++++ firestore/src/main/firestore_main.cc | 8 ++++---- firestore/src/main/firestore_main.h | 3 +-- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/firestore/src/common/firestore.cc b/firestore/src/common/firestore.cc index 6a2c2e4f1a..390a5ab1df 100644 --- a/firestore/src/common/firestore.cc +++ b/firestore/src/common/firestore.cc @@ -309,13 +309,17 @@ WriteBatch Firestore::batch() const { Future Firestore::RunTransaction( std::function update) { + return RunTransaction({}, std::move(update)); +} + +Future Firestore::RunTransaction(TransactionOptions options, std::function update) { if (!update) { SimpleThrowInvalidArgument( "Transaction update callback cannot be an empty function."); } if (!internal_) return FailedFuture(); - return internal_->RunTransaction(firebase::Move(update)); + return internal_->RunTransaction(firebase::Move(update), options.max_attempts()); } Future Firestore::DisableNetwork() { diff --git a/firestore/src/include/firebase/firestore.h b/firestore/src/include/firebase/firestore.h index c02ed21c5d..83e23cab63 100644 --- a/firestore/src/include/firebase/firestore.h +++ b/firestore/src/include/firebase/firestore.h @@ -254,6 +254,21 @@ class Firestore { virtual Future RunTransaction( std::function update); + /** + * Executes the given update and then attempts to commit the changes applied + * within the transaction. If any document read within the transaction has + * changed, the update function will be retried. If it fails to commit after + * the `max_attempts` specified in the given `TransactionOptions`, the + * transaction will fail. + * + * @param options The transaction options for controlling execution. + * @param update function or lambda to execute within the transaction context. + * The string reference parameter can be used to set the error message. + * + * @return A Future that will be resolved when the transaction finishes. + */ + virtual Future RunTransaction(TransactionOptions options, std::function update); + /** * Sets the log verbosity of all Firestore instances. * diff --git a/firestore/src/main/firestore_main.cc b/firestore/src/main/firestore_main.cc index c6d30c4d70..301cd6ce9f 100644 --- a/firestore/src/main/firestore_main.cc +++ b/firestore/src/main/firestore_main.cc @@ -197,8 +197,9 @@ WriteBatch FirestoreInternal::batch() const { return MakePublic(firestore_core_->GetBatch()); } -Future FirestoreInternal::RunTransaction( - std::function update) { +Future FirestoreInternal::RunTransaction(std::function update, int32_t max_attempts) { + SIMPLE_HARD_ASSERT(max_attempts > 0); + auto executor = transaction_executor_; auto promise = promise_factory_.CreatePromise(AsyncApi::kRunTransaction); @@ -244,8 +245,7 @@ Future FirestoreInternal::RunTransaction( } }; - firestore_core_->RunTransaction(std::move(update_callback), - std::move(final_result_callback)); + firestore_core_->RunTransaction(std::move(update_callback), std::move(final_result_callback), max_attempts); return promise.future(); } diff --git a/firestore/src/main/firestore_main.h b/firestore/src/main/firestore_main.h index 46000276ec..5f00af2a90 100644 --- a/firestore/src/main/firestore_main.h +++ b/firestore/src/main/firestore_main.h @@ -84,8 +84,7 @@ class FirestoreInternal { WriteBatch batch() const; - Future RunTransaction( - std::function update); + Future RunTransaction(std::function update, int32_t max_attempts); Future DisableNetwork(); From 04bb7420255f8e042f7a36691a8ce3f0e38552c8 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 16:20:07 -0400 Subject: [PATCH 16/47] transaction_test.cc: add test for specifying max_attempts to TransactionListener. --- .../src/transaction_test.cc | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/firestore/integration_test_internal/src/transaction_test.cc b/firestore/integration_test_internal/src/transaction_test.cc index a061eb333a..c25b9b94e4 100644 --- a/firestore/integration_test_internal/src/transaction_test.cc +++ b/firestore/integration_test_internal/src/transaction_test.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include +#include #include #include @@ -728,5 +730,65 @@ TEST_F(TransactionTest, TestCancellationOnError) { EXPECT_FALSE(snapshot.exists()); } +TEST_F(TransactionTest, TestMaxAttempts) { + Firestore* firestore = TestFirestore(); + DocumentReference doc = firestore->Collection("TestMaxAttempts").Document(); + + TransactionOptions options; + options.set_max_attempts(3); + + // Keep track of the number of times that the update callback is invoked. + auto update_count = std::make_shared(); + update_count->store(0); + + Future run_transaction_future = firestore->RunTransaction(options, [update_count, &doc](Transaction& transaction, std::string&) -> Error { + SCOPED_TRACE("Update callback; update_count=" + std::to_string(update_count->load())); + ++(*update_count); + + // Get the document via the transaction. + { + SCOPED_TRACE("transaction.Get()"); + Error error = Error::kErrorOk; + std::string error_message; + transaction.Get(doc, &error, &error_message); + if (error != kErrorOk) { + ADD_FAILURE() << "transaction.Get() failed: " << error_message << " (error code " << error << ")"; + return Error::kErrorInternal; + } + } + + // Modify the document *outside* of the transaction. + { + SCOPED_TRACE("doc.Set() outside of transaction"); + auto set_future = doc.Set({{"count", FieldValue::Integer(update_count->load())}}); + set_future.Await(10000L); + if (set_future.status() != FutureStatus::kFutureStatusComplete) { + ADD_FAILURE() << "Timeout waiting for doc.Set() to complete"; + return Error::kErrorInternal; + } else if (set_future.error() != Error::kErrorOk) { + ADD_FAILURE() << "doc.Set() failed: " << set_future.error_message() << " (error code " << set_future.error() << ")"; + return Error::kErrorInternal; + } + } + + // Modify the document *using* of the transaction. + // This will fail because the document was modified since we retrieved it + // via the transaction, and will result in a retry. + transaction.Set(doc, {{"count", FieldValue::String("this set should fail")}}); + + return Error::kErrorOk; + }); + + { + SCOPED_TRACE("Waiting for Future returned from RunTransaction()"); + Await(run_transaction_future); + ASSERT_EQ(run_transaction_future.status(), FutureStatus::kFutureStatusComplete); + EXPECT_EQ(run_transaction_future.error(), Error::kErrorFailedPrecondition) << "error message: " << run_transaction_future.error_message(); + } + + EXPECT_EQ(update_count->load(), 3); +} + + } // namespace firestore } // namespace firebase From b12fcc87d9604af074df7c64d01b8fd67da3f8a4 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 16:27:15 -0400 Subject: [PATCH 17/47] format code --- .../src/transaction_options_test.cc | 7 +- .../src/transaction_test.cc | 82 ++++++++++--------- firestore/src/common/firestore.cc | 7 +- firestore/src/common/transaction_options.cc | 6 +- firestore/src/include/firebase/firestore.h | 4 +- .../firebase/firestore/transaction_options.h | 10 ++- firestore/src/main/firestore_main.cc | 8 +- firestore/src/main/firestore_main.h | 4 +- 8 files changed, 77 insertions(+), 51 deletions(-) diff --git a/firestore/integration_test_internal/src/transaction_options_test.cc b/firestore/integration_test_internal/src/transaction_options_test.cc index 3b04883417..07aa2a068e 100644 --- a/firestore/integration_test_internal/src/transaction_options_test.cc +++ b/firestore/integration_test_internal/src/transaction_options_test.cc @@ -14,9 +14,9 @@ * limitations under the License. */ -#include #include #include +#include #include "firebase/firestore.h" #include "gtest/gtest.h" @@ -26,7 +26,10 @@ namespace firestore { namespace { TEST(TransactionOptionsTest, TypeTraits) { - static_assert(std::is_trivially_copyable::value, "Update the public doxygen comments about TransactionOptions being trivially copyable in the header file if it ever changes to NOT be trivially copyable."); + static_assert(std::is_trivially_copyable::value, + "Update the public doxygen comments about TransactionOptions " + "being trivially copyable in the header file if it ever " + "changes to NOT be trivially copyable."); } TEST(TransactionOptionsTest, DefaultConstructor) { diff --git a/firestore/integration_test_internal/src/transaction_test.cc b/firestore/integration_test_internal/src/transaction_test.cc index c25b9b94e4..12c47c837b 100644 --- a/firestore/integration_test_internal/src/transaction_test.cc +++ b/firestore/integration_test_internal/src/transaction_test.cc @@ -741,54 +741,62 @@ TEST_F(TransactionTest, TestMaxAttempts) { auto update_count = std::make_shared(); update_count->store(0); - Future run_transaction_future = firestore->RunTransaction(options, [update_count, &doc](Transaction& transaction, std::string&) -> Error { - SCOPED_TRACE("Update callback; update_count=" + std::to_string(update_count->load())); - ++(*update_count); - - // Get the document via the transaction. - { - SCOPED_TRACE("transaction.Get()"); - Error error = Error::kErrorOk; - std::string error_message; - transaction.Get(doc, &error, &error_message); - if (error != kErrorOk) { - ADD_FAILURE() << "transaction.Get() failed: " << error_message << " (error code " << error << ")"; - return Error::kErrorInternal; - } - } + Future run_transaction_future = firestore->RunTransaction( + options, + [update_count, &doc](Transaction& transaction, std::string&) -> Error { + SCOPED_TRACE("Update callback; update_count=" + + std::to_string(update_count->load())); + ++(*update_count); + + // Get the document via the transaction. + { + SCOPED_TRACE("transaction.Get()"); + Error error = Error::kErrorOk; + std::string error_message; + transaction.Get(doc, &error, &error_message); + if (error != kErrorOk) { + ADD_FAILURE() << "transaction.Get() failed: " << error_message + << " (error code " << error << ")"; + return Error::kErrorInternal; + } + } - // Modify the document *outside* of the transaction. - { - SCOPED_TRACE("doc.Set() outside of transaction"); - auto set_future = doc.Set({{"count", FieldValue::Integer(update_count->load())}}); - set_future.Await(10000L); - if (set_future.status() != FutureStatus::kFutureStatusComplete) { - ADD_FAILURE() << "Timeout waiting for doc.Set() to complete"; - return Error::kErrorInternal; - } else if (set_future.error() != Error::kErrorOk) { - ADD_FAILURE() << "doc.Set() failed: " << set_future.error_message() << " (error code " << set_future.error() << ")"; - return Error::kErrorInternal; - } - } + // Modify the document *outside* of the transaction. + { + SCOPED_TRACE("doc.Set() outside of transaction"); + auto set_future = + doc.Set({{"count", FieldValue::Integer(update_count->load())}}); + set_future.Await(10000L); + if (set_future.status() != FutureStatus::kFutureStatusComplete) { + ADD_FAILURE() << "Timeout waiting for doc.Set() to complete"; + return Error::kErrorInternal; + } else if (set_future.error() != Error::kErrorOk) { + ADD_FAILURE() << "doc.Set() failed: " << set_future.error_message() + << " (error code " << set_future.error() << ")"; + return Error::kErrorInternal; + } + } - // Modify the document *using* of the transaction. - // This will fail because the document was modified since we retrieved it - // via the transaction, and will result in a retry. - transaction.Set(doc, {{"count", FieldValue::String("this set should fail")}}); + // Modify the document *using* of the transaction. + // This will fail because the document was modified since we retrieved + // it via the transaction, and will result in a retry. + transaction.Set( + doc, {{"count", FieldValue::String("this set should fail")}}); - return Error::kErrorOk; - }); + return Error::kErrorOk; + }); { SCOPED_TRACE("Waiting for Future returned from RunTransaction()"); Await(run_transaction_future); - ASSERT_EQ(run_transaction_future.status(), FutureStatus::kFutureStatusComplete); - EXPECT_EQ(run_transaction_future.error(), Error::kErrorFailedPrecondition) << "error message: " << run_transaction_future.error_message(); + ASSERT_EQ(run_transaction_future.status(), + FutureStatus::kFutureStatusComplete); + EXPECT_EQ(run_transaction_future.error(), Error::kErrorFailedPrecondition) + << "error message: " << run_transaction_future.error_message(); } EXPECT_EQ(update_count->load(), 3); } - } // namespace firestore } // namespace firebase diff --git a/firestore/src/common/firestore.cc b/firestore/src/common/firestore.cc index 390a5ab1df..a7695a7b1a 100644 --- a/firestore/src/common/firestore.cc +++ b/firestore/src/common/firestore.cc @@ -312,14 +312,17 @@ Future Firestore::RunTransaction( return RunTransaction({}, std::move(update)); } -Future Firestore::RunTransaction(TransactionOptions options, std::function update) { +Future Firestore::RunTransaction( + TransactionOptions options, + std::function update) { if (!update) { SimpleThrowInvalidArgument( "Transaction update callback cannot be an empty function."); } if (!internal_) return FailedFuture(); - return internal_->RunTransaction(firebase::Move(update), options.max_attempts()); + return internal_->RunTransaction(firebase::Move(update), + options.max_attempts()); } Future Firestore::DisableNetwork() { diff --git a/firestore/src/common/transaction_options.cc b/firestore/src/common/transaction_options.cc index a4f4136015..1e48673f55 100644 --- a/firestore/src/common/transaction_options.cc +++ b/firestore/src/common/transaction_options.cc @@ -26,13 +26,15 @@ namespace firestore { void TransactionOptions::set_max_attempts(int32_t max_attempts) { if (max_attempts <= 0) { - SimpleThrowInvalidArgument("invalid max_attempts: " + std::to_string(max_attempts)); + SimpleThrowInvalidArgument("invalid max_attempts: " + + std::to_string(max_attempts)); } max_attempts_ = max_attempts; } std::string TransactionOptions::ToString() const { - return std::string("TransactionOptions(max_attempts=") + std::to_string(max_attempts()) + ")"; + return std::string("TransactionOptions(max_attempts=") + + std::to_string(max_attempts()) + ")"; } std::ostream& operator<<(std::ostream& out, const TransactionOptions& options) { diff --git a/firestore/src/include/firebase/firestore.h b/firestore/src/include/firebase/firestore.h index 83e23cab63..c35de11b4d 100644 --- a/firestore/src/include/firebase/firestore.h +++ b/firestore/src/include/firebase/firestore.h @@ -267,7 +267,9 @@ class Firestore { * * @return A Future that will be resolved when the transaction finishes. */ - virtual Future RunTransaction(TransactionOptions options, std::function update); + virtual Future RunTransaction( + TransactionOptions options, + std::function update); /** * Sets the log verbosity of all Firestore instances. diff --git a/firestore/src/include/firebase/firestore/transaction_options.h b/firestore/src/include/firebase/firestore/transaction_options.h index 3e588d97a2..9433578879 100644 --- a/firestore/src/include/firebase/firestore/transaction_options.h +++ b/firestore/src/include/firebase/firestore/transaction_options.h @@ -29,7 +29,6 @@ namespace firestore { */ class TransactionOptions final { public: - /** * @brief Creates the default `TransactionOptions`. */ @@ -84,14 +83,16 @@ class TransactionOptions final { TransactionOptions& operator=(TransactionOptions&& other) = default; /** - * @brief Gets the maximum number of attempts to commit, after which the transaction fails. + * @brief Gets the maximum number of attempts to commit, after which the + * transaction fails. * * The default value is 5. */ int32_t max_attempts() const { return max_attempts_; } /** - * @brief Sets the maximum number of attempts to commit, after which the transaction fails. + * @brief Sets the maximum number of attempts to commit, after which the + * transaction fails. * * The default value is 5. * @@ -125,7 +126,8 @@ class TransactionOptions final { bool operator==(const TransactionOptions&, const TransactionOptions&); /** Compares two `TransactionOptions` objects for inequality. */ -inline bool operator!=(const TransactionOptions& lhs, const TransactionOptions& rhs) { +inline bool operator!=(const TransactionOptions& lhs, + const TransactionOptions& rhs) { return !(lhs == rhs); } diff --git a/firestore/src/main/firestore_main.cc b/firestore/src/main/firestore_main.cc index 301cd6ce9f..9174665b7c 100644 --- a/firestore/src/main/firestore_main.cc +++ b/firestore/src/main/firestore_main.cc @@ -197,7 +197,9 @@ WriteBatch FirestoreInternal::batch() const { return MakePublic(firestore_core_->GetBatch()); } -Future FirestoreInternal::RunTransaction(std::function update, int32_t max_attempts) { +Future FirestoreInternal::RunTransaction( + std::function update, + int32_t max_attempts) { SIMPLE_HARD_ASSERT(max_attempts > 0); auto executor = transaction_executor_; @@ -245,7 +247,9 @@ Future FirestoreInternal::RunTransaction(std::functionRunTransaction(std::move(update_callback), std::move(final_result_callback), max_attempts); + firestore_core_->RunTransaction(std::move(update_callback), + std::move(final_result_callback), + max_attempts); return promise.future(); } diff --git a/firestore/src/main/firestore_main.h b/firestore/src/main/firestore_main.h index 5f00af2a90..68c02e2e49 100644 --- a/firestore/src/main/firestore_main.h +++ b/firestore/src/main/firestore_main.h @@ -84,7 +84,9 @@ class FirestoreInternal { WriteBatch batch() const; - Future RunTransaction(std::function update, int32_t max_attempts); + Future RunTransaction( + std::function update, + int32_t max_attempts); Future DisableNetwork(); From 184460701e556fbf8c5751fd9f4498a161ef8ec1 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 25 May 2022 16:33:02 -0400 Subject: [PATCH 18/47] release_build_files/readme.md: release notes entry added --- release_build_files/readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release_build_files/readme.md b/release_build_files/readme.md index b78e3af194..f7b4e402c1 100644 --- a/release_build_files/readme.md +++ b/release_build_files/readme.md @@ -605,6 +605,9 @@ code. only using AdMob, Analytics, Remote Config, or Messaging. - Functions: Add a new method `GetHttpsCallableFromURL`, to create callables with URLs other than cloudfunctions.net. + - Firestore: Added `TransactionOptions` to control how many times a + transaction will retry commits before failing + ([#966](https://github.com/firebase/firebase-cpp-sdk/pull/966)). ### 9.0.0 - Changes From ce9ca4f46c821d99def4dee18d5b775444ff6264 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Thu, 26 May 2022 16:28:50 -0400 Subject: [PATCH 19/47] firestore.cmake: update pinned commit to https://github.com/firebase/firebase-cpp-sdk/pull/967, which fixes a problematic python_setup.cmake bug --- cmake/external/firestore.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index e7c6898f58..bd7e5e14e5 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -37,9 +37,9 @@ function(GetReleasedDep) DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} GIT_REPOSITORY "https://github.com/firebase/firebase-ios-sdk.git" - # Pinned HEAD commit after https://github.com/firebase/firebase-ios-sdk/pull/9596 - # (Enable Snappy compression support in LevelDb in cmake builds) was merged. - GIT_TAG c0df0d4ab11d4ae30c307a0c7dcdb29e3e0dc411 + # Pinned commit in https://github.com/firebase/firebase-cpp-sdk/pull/967, which fixes a + # problematic python_setup.cmake bug. + GIT_TAG 0dbc5dd788e8c41b1530e6b392df739be223948c PREFIX ${PROJECT_BINARY_DIR} From c834bc6e4595d47d8ebfc887bc8c54bb6ad0682c Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 00:04:11 -0400 Subject: [PATCH 20/47] firestore.cmake: update pinned commit to https://github.com/firebase/firebase-ios-sdk/pull/9851, which fixes a problematic usage of designated initialization --- cmake/external/firestore.cmake | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index bd7e5e14e5..ea5171a9d3 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -37,9 +37,11 @@ function(GetReleasedDep) DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} GIT_REPOSITORY "https://github.com/firebase/firebase-ios-sdk.git" - # Pinned commit in https://github.com/firebase/firebase-cpp-sdk/pull/967, which fixes a - # problematic python_setup.cmake bug. - GIT_TAG 0dbc5dd788e8c41b1530e6b392df739be223948c + # Pinned commit in https://github.com/firebase/firebase-ios-sdk/pull/9851 which fixes a + # problematic usage of designated initialization. This commit also includes + # https://github.com/firebase/firebase-ios-sdk/pull/9847, which fixes a problematic bug in + # python_setup.cmake. + GIT_TAG f2fb419cd3332ac74be0a7076841b2162a96060d PREFIX ${PROJECT_BINARY_DIR} From b39452a83d80216e9be5b2d201cc0c8578e99407 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 00:12:19 -0400 Subject: [PATCH 21/47] cherry-pick bundle_test.cc: Disable LoadBundleWithDocumentsAlreadyPulledFromBackend (https://github.com/firebase/firebase-cpp-sdk/pull/972) --- firestore/integration_test_internal/src/bundle_test.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firestore/integration_test_internal/src/bundle_test.cc b/firestore/integration_test_internal/src/bundle_test.cc index 3ac9760a9f..d1b5980073 100644 --- a/firestore/integration_test_internal/src/bundle_test.cc +++ b/firestore/integration_test_internal/src/bundle_test.cc @@ -277,6 +277,9 @@ TEST_F(BundleTest, LoadBundleWithDocumentsAlreadyPulledFromBackend) { // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; + GTEST_SKIP() << "This test fails often on Android and iOS in GitHub Actions " + "and needs to be investigated (b/233751585)"; + Firestore* db = TestFirestore(); auto collection = db->Collection("coll-1"); WriteDocuments(collection, From f8e38b1862f3d0f9adb06b6591bcce57a2293b2f Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 10:01:30 -0400 Subject: [PATCH 22/47] bundle_test.cc: disable ALL of the tests --- .../src/bundle_test.cc | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/firestore/integration_test_internal/src/bundle_test.cc b/firestore/integration_test_internal/src/bundle_test.cc index d1b5980073..3cc1ee5be4 100644 --- a/firestore/integration_test_internal/src/bundle_test.cc +++ b/firestore/integration_test_internal/src/bundle_test.cc @@ -142,6 +142,9 @@ class BundleTest : public FirestoreIntegrationTest { }; TEST_F(BundleTest, CanLoadBundlesWithoutProgressUpdates) { + GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " + "Actions and needs to be investigated (b/233751585)"; + Firestore* db = TestFirestore(); auto bundle = CreateTestBundle(db); @@ -152,6 +155,9 @@ TEST_F(BundleTest, CanLoadBundlesWithoutProgressUpdates) { } TEST_F(BundleTest, CanLoadBundlesWithProgressUpdates) { + GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " + "Actions and needs to be investigated (b/233751585)"; + Firestore* db = TestFirestore(); auto bundle = CreateTestBundle(db); @@ -180,6 +186,9 @@ TEST_F(BundleTest, CanLoadBundlesWithProgressUpdates) { } TEST_F(BundleTest, CanDeleteFirestoreFromProgressUpdate) { + GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " + "Actions and needs to be investigated (b/233751585)"; + Firestore* db = TestFirestore(); auto bundle = CreateTestBundle(db); @@ -216,6 +225,9 @@ TEST_F(BundleTest, CanDeleteFirestoreFromProgressUpdate) { } TEST_F(BundleTest, LoadBundlesForASecondTimeSkips) { + GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " + "Actions and needs to be investigated (b/233751585)"; + // TODO(wuandy): This test fails on Windows CI, but // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; @@ -244,6 +256,9 @@ TEST_F(BundleTest, LoadBundlesForASecondTimeSkips) { } TEST_F(BundleTest, LoadInvalidBundlesShouldFail) { + GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " + "Actions and needs to be investigated (b/233751585)"; + // TODO(wuandy): This test fails on Windows CI, but // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; @@ -273,13 +288,13 @@ TEST_F(BundleTest, LoadInvalidBundlesShouldFail) { } TEST_F(BundleTest, LoadBundleWithDocumentsAlreadyPulledFromBackend) { + GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " + "Actions and needs to be investigated (b/233751585)"; + // TODO(wuandy, b/189477267): This test fails on Windows CI, but // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; - GTEST_SKIP() << "This test fails often on Android and iOS in GitHub Actions " - "and needs to be investigated (b/233751585)"; - Firestore* db = TestFirestore(); auto collection = db->Collection("coll-1"); WriteDocuments(collection, @@ -322,6 +337,9 @@ TEST_F(BundleTest, LoadBundleWithDocumentsAlreadyPulledFromBackend) { } TEST_F(BundleTest, LoadedDocumentsShouldNotBeGarbageCollectedRightAway) { + GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " + "Actions and needs to be investigated (b/233751585)"; + // TODO(wuandy, b/189477267): This test fails on Windows CI, but // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; @@ -346,6 +364,9 @@ TEST_F(BundleTest, LoadedDocumentsShouldNotBeGarbageCollectedRightAway) { } TEST_F(BundleTest, LoadDocumentsFromOtherProjectsShouldFail) { + GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " + "Actions and needs to be investigated (b/233751585)"; + Firestore* db = TestFirestore(); auto bundle = CreateBundle("other-project"); std::vector progresses; @@ -366,6 +387,9 @@ TEST_F(BundleTest, LoadDocumentsFromOtherProjectsShouldFail) { } TEST_F(BundleTest, GetInvalidNamedQuery) { + GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " + "Actions and needs to be investigated (b/233751585)"; + Firestore* db = TestFirestore(); { auto future = db->NamedQuery("DOES_NOT_EXIST"); From 0fe44d987976d2475cd97edea27a4692b739c466 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 11:50:18 -0400 Subject: [PATCH 23/47] DO NOT MERGE: Android/firebase_dependencies.gradle: use snapshot version of firestore --- Android/firebase_dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android/firebase_dependencies.gradle b/Android/firebase_dependencies.gradle index 11424af0c0..e2122b2333 100644 --- a/Android/firebase_dependencies.gradle +++ b/Android/firebase_dependencies.gradle @@ -24,7 +24,7 @@ def firebaseDependenciesMap = [ 'auth' : ['com.google.firebase:firebase-auth:21.0.3'], 'database' : ['com.google.firebase:firebase-database:20.0.5'], 'dynamic_links' : ['com.google.firebase:firebase-dynamic-links:21.0.1'], - 'firestore' : ['com.google.firebase:firebase-firestore:24.1.2'], + 'firestore' : ['com.google.firebase:firebase-firestore:24.1.3-SNAPSHOT'], 'functions' : ['com.google.firebase:firebase-functions:20.1.0'], 'installations' : ['com.google.firebase:firebase-installations:17.0.1'], 'invites' : ['com.google.firebase:firebase-invites:17.0.0'], From 809a98fff03225c7c700f220951a001afd281d5e Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 11:54:25 -0400 Subject: [PATCH 24/47] DO NOT MERGE: local build optimizations to build.gradle and gradle.properties and settings.gradle --- firestore/integration_test_internal/build.gradle | 2 ++ .../integration_test_internal/gradle.properties | 1 + settings.gradle | 15 +-------------- 3 files changed, 4 insertions(+), 14 deletions(-) create mode 100644 firestore/integration_test_internal/gradle.properties diff --git a/firestore/integration_test_internal/build.gradle b/firestore/integration_test_internal/build.gradle index 25113987cf..1edc7c2606 100644 --- a/firestore/integration_test_internal/build.gradle +++ b/firestore/integration_test_internal/build.gradle @@ -60,6 +60,8 @@ android { versionName '1.0' externalNativeBuild.cmake { arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir" + abiFilters 'x86_64' + targets 'firebase_firestore', 'firebase_auth', 'android_integration_test_main' } multiDexEnabled true } diff --git a/firestore/integration_test_internal/gradle.properties b/firestore/integration_test_internal/gradle.properties new file mode 100644 index 0000000000..3b275c45cf --- /dev/null +++ b/firestore/integration_test_internal/gradle.properties @@ -0,0 +1 @@ +systemProp.firebase_cpp_sdk.dir=/home/dconeybe/dev/firebase/cpp diff --git a/settings.gradle b/settings.gradle index 07828daea2..834f51e0e3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,20 +3,7 @@ include ':app', ':app:app_resources', ':app:google_api_resources', ':app:invites_resources', - ':admob', - ':admob:admob_resources', - ':analytics', ':auth', ':auth:auth_resources', - ':database', - ':database:database_resources', - ':dynamic_links', ':firestore', - ':firestore:firestore_resources', - ':functions', - ':installations', - ':messaging', - ':messaging:messaging_java', - ':remote_config', - ':storage', - ':storage:storage_resources' \ No newline at end of file + ':firestore:firestore_resources' From 47f854b3f671a5dfd4eb398c65bfa625058887a5 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 13:51:23 -0400 Subject: [PATCH 25/47] Android implementation (untested, and needs tests) --- firestore/CMakeLists.txt | 4 ++ firestore/src/android/firestore_android.cc | 10 +++- firestore/src/android/firestore_android.h | 3 +- .../android/transaction_options_android.cc | 47 +++++++++++++++ .../src/android/transaction_options_android.h | 38 +++++++++++++ .../transaction_options_builder_android.cc | 57 +++++++++++++++++++ .../transaction_options_builder_android.h | 43 ++++++++++++++ 7 files changed, 198 insertions(+), 4 deletions(-) create mode 100644 firestore/src/android/transaction_options_android.cc create mode 100644 firestore/src/android/transaction_options_android.h create mode 100644 firestore/src/android/transaction_options_builder_android.cc create mode 100644 firestore/src/android/transaction_options_builder_android.h diff --git a/firestore/CMakeLists.txt b/firestore/CMakeLists.txt index e989317537..84730a8b51 100644 --- a/firestore/CMakeLists.txt +++ b/firestore/CMakeLists.txt @@ -128,6 +128,10 @@ set(android_SRCS src/android/timestamp_portable.cc src/android/transaction_android.cc src/android/transaction_android.h + src/android/transaction_options_android.cc + src/android/transaction_options_android.h + src/android/transaction_options_builder_android.cc + src/android/transaction_options_builder_android.h src/android/util_android.cc src/android/util_android.h src/android/wrapper.cc diff --git a/firestore/src/android/firestore_android.cc b/firestore/src/android/firestore_android.cc index 765af93eac..e0e9d5ab41 100644 --- a/firestore/src/android/firestore_android.cc +++ b/firestore/src/android/firestore_android.cc @@ -52,8 +52,11 @@ #include "firestore/src/android/source_android.h" #include "firestore/src/android/timestamp_android.h" #include "firestore/src/android/transaction_android.h" +#include "firestore/src/android/transaction_options_android.h" +#include "firestore/src/android/transaction_options_builder_android.h" #include "firestore/src/android/wrapper.h" #include "firestore/src/android/write_batch_android.h" +#include "firestore/src/common/hard_assert_common.h" #include "firestore/src/common/make_unique.h" #include "firestore/src/include/firebase/firestore.h" #include "firestore/src/jni/array.h" @@ -339,6 +342,8 @@ bool FirestoreInternal::Initialize(App* app) { Task::Initialize(loader); TimestampInternal::Initialize(loader); TransactionInternal::Initialize(loader); + TransactionOptionsBuilderInternal::Initialize(loader); + TransactionOptionsInternal::Initialize(loader); WriteBatchInternal::Initialize(loader); LoadBundleTaskInternal::Initialize(loader); LoadBundleTaskProgressInternal::Initialize(loader); @@ -454,8 +459,9 @@ WriteBatch FirestoreInternal::batch() const { return WriteBatch(new WriteBatchInternal(mutable_this(), result)); } -Future FirestoreInternal::RunTransaction( - std::function update) { +Future FirestoreInternal::RunTransaction(std::function update, int32_t max_attempts) { + SIMPLE_HARD_ASSERT(max_attempts > 0); + auto* lambda_update = new LambdaTransactionFunction(Move(update)); Env env = GetEnv(); Local transaction_function = diff --git a/firestore/src/android/firestore_android.h b/firestore/src/android/firestore_android.h index 73a8b0a37c..56c19ef09e 100644 --- a/firestore/src/android/firestore_android.h +++ b/firestore/src/android/firestore_android.h @@ -107,8 +107,7 @@ class FirestoreInternal { WriteBatch batch() const; - Future RunTransaction( - std::function update); + Future RunTransaction(std::function update, int32_t max_attempts); // Disables network and gets anything from cache instead of server. Future DisableNetwork(); diff --git a/firestore/src/android/transaction_options_android.cc b/firestore/src/android/transaction_options_android.cc new file mode 100644 index 0000000000..c038292ce0 --- /dev/null +++ b/firestore/src/android/transaction_options_android.cc @@ -0,0 +1,47 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "firestore/src/android/transaction_options_android.h" + +#include "firestore/src/jni/env.h" +#include "firestore/src/jni/loader.h" + +namespace firebase { +namespace firestore { +namespace { + +using jni::Constructor; +using jni::Env; +using jni::Local; +using jni::Method; +using jni::Object; +using jni::String; + +constexpr char kTransactionOptionsClass[] = PROGUARD_KEEP_CLASS "com/google/firebase/firestore/TransactionOptions"; +Method kGetMaxAttempts("getMaxAttempts", "()I"); + +} // namespace + +void TransactionOptionsInternal::Initialize(jni::Loader& loader) { + loader.LoadClass(kTransactionOptionsClass, kGetMaxAttempts); +} + +int32_t TransactionOptionsInternal::GetMaxAttempts(jni::Env& env) const { + return env.Call(*this, kGetMaxAttempts); +} + +} // namespace firestore +} // namespace firebase diff --git a/firestore/src/android/transaction_options_android.h b/firestore/src/android/transaction_options_android.h new file mode 100644 index 0000000000..21a864f244 --- /dev/null +++ b/firestore/src/android/transaction_options_android.h @@ -0,0 +1,38 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBASE_FIRESTORE_SRC_ANDROID_TRANSACTION_OPTIONS_ANDROID_H_ +#define FIREBASE_FIRESTORE_SRC_ANDROID_TRANSACTION_OPTIONS_ANDROID_H_ + +#include "firestore/src/jni/jni_fwd.h" +#include "firestore/src/jni/object.h" + +namespace firebase { +namespace firestore { + +class TransactionOptionsInternal : public jni::Object { + public: + using jni::Object::Object; + + static void Initialize(jni::Loader& loader); + + int32_t GetMaxAttempts(jni::Env&) const; +}; + +} // namespace firestore +} // namespace firebase + +#endif // FIREBASE_FIRESTORE_SRC_ANDROID_TRANSACTION_OPTIONS_ANDROID_H_ diff --git a/firestore/src/android/transaction_options_builder_android.cc b/firestore/src/android/transaction_options_builder_android.cc new file mode 100644 index 0000000000..f5b3890a66 --- /dev/null +++ b/firestore/src/android/transaction_options_builder_android.cc @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "firestore/src/android/transaction_options_builder_android.h" + +#include "firestore/src/jni/env.h" +#include "firestore/src/jni/loader.h" + +namespace firebase { +namespace firestore { +namespace { + +using jni::Constructor; +using jni::Env; +using jni::Local; +using jni::Method; +using jni::Object; +using jni::String; + +constexpr char kTransactionOptionsBuilderClass[] = PROGUARD_KEEP_CLASS "com/google/firebase/firestore/TransactionOptions$Builder"; +Constructor kNewBuilder("()V"); +Method kSetMaxAttempts("setMaxAttempts", "(I)Lcom/google/firebase/firestore/TransactionOptions$Builder;"); +Method kBuild("build", "()Lcom/google/firebase/firestore/TransactionOptions;"); + +} // namespace + +void TransactionOptionsBuilderInternal::Initialize(jni::Loader& loader) { + loader.LoadClass(kTransactionOptionsBuilderClass, kNewBuilder, kSetMaxAttempts, kBuild); +} + +Local TransactionOptionsBuilderInternal::Create(Env& env) { + return env.New(kNewBuilder); +} + +jni::Local TransactionOptionsBuilderInternal::SetMaxAttempts(jni::Env& env, int32_t max_attempts) const { + return env.Call(*this, kSetMaxAttempts, max_attempts); +} + +jni::Local TransactionOptionsBuilderInternal::Build(jni::Env& env) const { + return env.Call(*this, kBuild); +} + +} // namespace firestore +} // namespace firebase diff --git a/firestore/src/android/transaction_options_builder_android.h b/firestore/src/android/transaction_options_builder_android.h new file mode 100644 index 0000000000..708cce2da5 --- /dev/null +++ b/firestore/src/android/transaction_options_builder_android.h @@ -0,0 +1,43 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBASE_FIRESTORE_SRC_ANDROID_TRANSACTION_OPTIONS_BUILDER_ANDROID_H_ +#define FIREBASE_FIRESTORE_SRC_ANDROID_TRANSACTION_OPTIONS_BUILDER_ANDROID_H_ + +#include "firestore/src/android/transaction_options_android.h" +#include "firestore/src/jni/jni_fwd.h" +#include "firestore/src/jni/object.h" + +namespace firebase { +namespace firestore { + +class TransactionOptionsBuilderInternal : public jni::Object { + public: + using jni::Object::Object; + + static void Initialize(jni::Loader& loader); + + static jni::Local Create(jni::Env&); + + jni::Local SetMaxAttempts(jni::Env&, int32_t max_attempts) const; + + jni::Local Build(jni::Env&) const; +}; + +} // namespace firestore +} // namespace firebase + +#endif // FIREBASE_FIRESTORE_SRC_ANDROID_TRANSACTION_OPTIONS_BUILDER_ANDROID_H_ From f92537ea6b324f830a91d48b3bd71d1033da6500 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 14:14:39 -0400 Subject: [PATCH 26/47] transaction_options_android_test.cc added --- .../integration_test_internal/CMakeLists.txt | 1 + .../transaction_options_android_test.cc | 63 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 firestore/integration_test_internal/src/android/transaction_options_android_test.cc diff --git a/firestore/integration_test_internal/CMakeLists.txt b/firestore/integration_test_internal/CMakeLists.txt index 664236b946..fd80ab2656 100644 --- a/firestore/integration_test_internal/CMakeLists.txt +++ b/firestore/integration_test_internal/CMakeLists.txt @@ -117,6 +117,7 @@ set(FIREBASE_INTEGRATION_TEST_ANDROID_TEST_SRCS src/android/settings_android_test.cc src/android/snapshot_metadata_android_test.cc src/android/timestamp_android_test.cc + src/android/transaction_options_android_test.cc src/jni/declaration_test.cc src/jni/env_test.cc src/jni/object_test.cc diff --git a/firestore/integration_test_internal/src/android/transaction_options_android_test.cc b/firestore/integration_test_internal/src/android/transaction_options_android_test.cc new file mode 100644 index 0000000000..ffaceb2b4a --- /dev/null +++ b/firestore/integration_test_internal/src/android/transaction_options_android_test.cc @@ -0,0 +1,63 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "firestore/src/android/transaction_options_android.h" +#include "firestore/src/android/transaction_options_builder_android.h" + +#include "firestore/src/jni/env.h" +#include "firestore_integration_test.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace firebase { +namespace firestore { +namespace { + +using jni::Env; +using jni::Local; + +using TransactionOptionsTestAndroid = FirestoreIntegrationTest; + +TEST_F(TransactionOptionsTestAndroid, DefaultTransactionOptions) { + Env env; + Local builder = TransactionOptionsBuilderInternal::Create(env); + + Local options = builder.Build(env); + + EXPECT_EQ(options.GetMaxAttempts(env), 5); +} + +TEST_F(TransactionOptionsTestAndroid, SetMaxAttemptsReturnsSameInstance) { + Env env; + Local builder = TransactionOptionsBuilderInternal::Create(env); + + Local retval = builder.SetMaxAttempts(env, 42); + + EXPECT_TRUE(env.IsSameObject(builder, retval)); +} + +TEST_F(TransactionOptionsTestAndroid, SetMaxAttempts) { + Env env; + Local builder = TransactionOptionsBuilderInternal::Create(env); + + builder.SetMaxAttempts(env, 42); + + EXPECT_EQ(builder.Build(env).GetMaxAttempts(env), 42); +} + +} // namespace +} // namespace firestore +} // namespace firebase From 44b39012cebf6e13ecf8bf5b6b524c191f3b45d4 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 14:21:23 -0400 Subject: [PATCH 27/47] firestore_android.cc: pass through max_attempts --- firestore/src/android/firestore_android.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/firestore/src/android/firestore_android.cc b/firestore/src/android/firestore_android.cc index e0e9d5ab41..e05f0f1e6c 100644 --- a/firestore/src/android/firestore_android.cc +++ b/firestore/src/android/firestore_android.cc @@ -123,7 +123,8 @@ Method kSetSettings( Method kBatch("batch", "()Lcom/google/firebase/firestore/WriteBatch;"); Method kRunTransaction( "runTransaction", - "(Lcom/google/firebase/firestore/Transaction$Function;)" + "(Lcom/google/firebase/firestore/TransactionOptions;" + "Lcom/google/firebase/firestore/Transaction$Function;)" "Lcom/google/android/gms/tasks/Task;"); Method kEnableNetwork("enableNetwork", "()Lcom/google/android/gms/tasks/Task;"); @@ -466,7 +467,13 @@ Future FirestoreInternal::RunTransaction(std::function transaction_function = TransactionInternal::Create(env, this, lambda_update); - Local task = env.Call(obj_, kRunTransaction, transaction_function); + + Local options_builder = TransactionOptionsBuilderInternal::Create(env); + options_builder.SetMaxAttempts(env, max_attempts); + Local options = options_builder.Build(env); + options_builder.clear(); + + Local task = env.Call(obj_, kRunTransaction, options, transaction_function); if (!env.ok()) return {}; From 9cc10138089d72ec48e8dea85ffb1e67e6ff6955 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 14:31:07 -0400 Subject: [PATCH 28/47] clean up includes --- .../src/android/transaction_options_android.cc | 10 ++++------ .../android/transaction_options_builder_android.cc | 13 +++++++------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/firestore/src/android/transaction_options_android.cc b/firestore/src/android/transaction_options_android.cc index c038292ce0..5c78b2919a 100644 --- a/firestore/src/android/transaction_options_android.cc +++ b/firestore/src/android/transaction_options_android.cc @@ -16,6 +16,7 @@ #include "firestore/src/android/transaction_options_android.h" +#include "firestore/src/jni/declaration.h" #include "firestore/src/jni/env.h" #include "firestore/src/jni/loader.h" @@ -23,23 +24,20 @@ namespace firebase { namespace firestore { namespace { -using jni::Constructor; using jni::Env; -using jni::Local; +using jni::Loader; using jni::Method; -using jni::Object; -using jni::String; constexpr char kTransactionOptionsClass[] = PROGUARD_KEEP_CLASS "com/google/firebase/firestore/TransactionOptions"; Method kGetMaxAttempts("getMaxAttempts", "()I"); } // namespace -void TransactionOptionsInternal::Initialize(jni::Loader& loader) { +void TransactionOptionsInternal::Initialize(Loader& loader) { loader.LoadClass(kTransactionOptionsClass, kGetMaxAttempts); } -int32_t TransactionOptionsInternal::GetMaxAttempts(jni::Env& env) const { +int32_t TransactionOptionsInternal::GetMaxAttempts(Env& env) const { return env.Call(*this, kGetMaxAttempts); } diff --git a/firestore/src/android/transaction_options_builder_android.cc b/firestore/src/android/transaction_options_builder_android.cc index f5b3890a66..60f8d4e9b6 100644 --- a/firestore/src/android/transaction_options_builder_android.cc +++ b/firestore/src/android/transaction_options_builder_android.cc @@ -16,8 +16,10 @@ #include "firestore/src/android/transaction_options_builder_android.h" +#include "firestore/src/jni/declaration.h" #include "firestore/src/jni/env.h" #include "firestore/src/jni/loader.h" +#include "firestore/src/jni/ownership.h" namespace firebase { namespace firestore { @@ -25,10 +27,9 @@ namespace { using jni::Constructor; using jni::Env; -using jni::Local; using jni::Method; -using jni::Object; -using jni::String; +using jni::Loader; +using jni::Local; constexpr char kTransactionOptionsBuilderClass[] = PROGUARD_KEEP_CLASS "com/google/firebase/firestore/TransactionOptions$Builder"; Constructor kNewBuilder("()V"); @@ -37,7 +38,7 @@ Method kBuild("build", "()Lcom/google/firebase/fires } // namespace -void TransactionOptionsBuilderInternal::Initialize(jni::Loader& loader) { +void TransactionOptionsBuilderInternal::Initialize(Loader& loader) { loader.LoadClass(kTransactionOptionsBuilderClass, kNewBuilder, kSetMaxAttempts, kBuild); } @@ -45,11 +46,11 @@ Local TransactionOptionsBuilderInternal::Crea return env.New(kNewBuilder); } -jni::Local TransactionOptionsBuilderInternal::SetMaxAttempts(jni::Env& env, int32_t max_attempts) const { +Local TransactionOptionsBuilderInternal::SetMaxAttempts(Env& env, int32_t max_attempts) const { return env.Call(*this, kSetMaxAttempts, max_attempts); } -jni::Local TransactionOptionsBuilderInternal::Build(jni::Env& env) const { +Local TransactionOptionsBuilderInternal::Build(Env& env) const { return env.Call(*this, kBuild); } From 6356d3c9667fbd6ed63a0e1243884b807ac9a7dd Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 14:34:11 -0400 Subject: [PATCH 29/47] format code --- .../transaction_options_android_test.cc | 12 ++++++--- firestore/src/android/firestore_android.cc | 10 +++++--- firestore/src/android/firestore_android.h | 4 ++- .../android/transaction_options_android.cc | 3 ++- .../transaction_options_builder_android.cc | 25 +++++++++++++------ .../transaction_options_builder_android.h | 3 ++- 6 files changed, 39 insertions(+), 18 deletions(-) diff --git a/firestore/integration_test_internal/src/android/transaction_options_android_test.cc b/firestore/integration_test_internal/src/android/transaction_options_android_test.cc index ffaceb2b4a..aa12fe54f7 100644 --- a/firestore/integration_test_internal/src/android/transaction_options_android_test.cc +++ b/firestore/integration_test_internal/src/android/transaction_options_android_test.cc @@ -33,7 +33,8 @@ using TransactionOptionsTestAndroid = FirestoreIntegrationTest; TEST_F(TransactionOptionsTestAndroid, DefaultTransactionOptions) { Env env; - Local builder = TransactionOptionsBuilderInternal::Create(env); + Local builder = + TransactionOptionsBuilderInternal::Create(env); Local options = builder.Build(env); @@ -42,16 +43,19 @@ TEST_F(TransactionOptionsTestAndroid, DefaultTransactionOptions) { TEST_F(TransactionOptionsTestAndroid, SetMaxAttemptsReturnsSameInstance) { Env env; - Local builder = TransactionOptionsBuilderInternal::Create(env); + Local builder = + TransactionOptionsBuilderInternal::Create(env); - Local retval = builder.SetMaxAttempts(env, 42); + Local retval = + builder.SetMaxAttempts(env, 42); EXPECT_TRUE(env.IsSameObject(builder, retval)); } TEST_F(TransactionOptionsTestAndroid, SetMaxAttempts) { Env env; - Local builder = TransactionOptionsBuilderInternal::Create(env); + Local builder = + TransactionOptionsBuilderInternal::Create(env); builder.SetMaxAttempts(env, 42); diff --git a/firestore/src/android/firestore_android.cc b/firestore/src/android/firestore_android.cc index e05f0f1e6c..62917accd8 100644 --- a/firestore/src/android/firestore_android.cc +++ b/firestore/src/android/firestore_android.cc @@ -460,7 +460,9 @@ WriteBatch FirestoreInternal::batch() const { return WriteBatch(new WriteBatchInternal(mutable_this(), result)); } -Future FirestoreInternal::RunTransaction(std::function update, int32_t max_attempts) { +Future FirestoreInternal::RunTransaction( + std::function update, + int32_t max_attempts) { SIMPLE_HARD_ASSERT(max_attempts > 0); auto* lambda_update = new LambdaTransactionFunction(Move(update)); @@ -468,12 +470,14 @@ Future FirestoreInternal::RunTransaction(std::function transaction_function = TransactionInternal::Create(env, this, lambda_update); - Local options_builder = TransactionOptionsBuilderInternal::Create(env); + Local options_builder = + TransactionOptionsBuilderInternal::Create(env); options_builder.SetMaxAttempts(env, max_attempts); Local options = options_builder.Build(env); options_builder.clear(); - Local task = env.Call(obj_, kRunTransaction, options, transaction_function); + Local task = + env.Call(obj_, kRunTransaction, options, transaction_function); if (!env.ok()) return {}; diff --git a/firestore/src/android/firestore_android.h b/firestore/src/android/firestore_android.h index 56c19ef09e..5c5367a8f5 100644 --- a/firestore/src/android/firestore_android.h +++ b/firestore/src/android/firestore_android.h @@ -107,7 +107,9 @@ class FirestoreInternal { WriteBatch batch() const; - Future RunTransaction(std::function update, int32_t max_attempts); + Future RunTransaction( + std::function update, + int32_t max_attempts); // Disables network and gets anything from cache instead of server. Future DisableNetwork(); diff --git a/firestore/src/android/transaction_options_android.cc b/firestore/src/android/transaction_options_android.cc index 5c78b2919a..942874f7d8 100644 --- a/firestore/src/android/transaction_options_android.cc +++ b/firestore/src/android/transaction_options_android.cc @@ -28,7 +28,8 @@ using jni::Env; using jni::Loader; using jni::Method; -constexpr char kTransactionOptionsClass[] = PROGUARD_KEEP_CLASS "com/google/firebase/firestore/TransactionOptions"; +constexpr char kTransactionOptionsClass[] = + PROGUARD_KEEP_CLASS "com/google/firebase/firestore/TransactionOptions"; Method kGetMaxAttempts("getMaxAttempts", "()I"); } // namespace diff --git a/firestore/src/android/transaction_options_builder_android.cc b/firestore/src/android/transaction_options_builder_android.cc index 60f8d4e9b6..51d6223419 100644 --- a/firestore/src/android/transaction_options_builder_android.cc +++ b/firestore/src/android/transaction_options_builder_android.cc @@ -27,30 +27,39 @@ namespace { using jni::Constructor; using jni::Env; -using jni::Method; using jni::Loader; using jni::Local; +using jni::Method; -constexpr char kTransactionOptionsBuilderClass[] = PROGUARD_KEEP_CLASS "com/google/firebase/firestore/TransactionOptions$Builder"; +constexpr char kTransactionOptionsBuilderClass[] = PROGUARD_KEEP_CLASS + "com/google/firebase/firestore/TransactionOptions$Builder"; Constructor kNewBuilder("()V"); -Method kSetMaxAttempts("setMaxAttempts", "(I)Lcom/google/firebase/firestore/TransactionOptions$Builder;"); -Method kBuild("build", "()Lcom/google/firebase/firestore/TransactionOptions;"); +Method kSetMaxAttempts( + "setMaxAttempts", + "(I)Lcom/google/firebase/firestore/TransactionOptions$Builder;"); +Method kBuild( + "build", "()Lcom/google/firebase/firestore/TransactionOptions;"); } // namespace void TransactionOptionsBuilderInternal::Initialize(Loader& loader) { - loader.LoadClass(kTransactionOptionsBuilderClass, kNewBuilder, kSetMaxAttempts, kBuild); + loader.LoadClass(kTransactionOptionsBuilderClass, kNewBuilder, + kSetMaxAttempts, kBuild); } -Local TransactionOptionsBuilderInternal::Create(Env& env) { +Local +TransactionOptionsBuilderInternal::Create(Env& env) { return env.New(kNewBuilder); } -Local TransactionOptionsBuilderInternal::SetMaxAttempts(Env& env, int32_t max_attempts) const { +Local +TransactionOptionsBuilderInternal::SetMaxAttempts(Env& env, + int32_t max_attempts) const { return env.Call(*this, kSetMaxAttempts, max_attempts); } -Local TransactionOptionsBuilderInternal::Build(Env& env) const { +Local TransactionOptionsBuilderInternal::Build( + Env& env) const { return env.Call(*this, kBuild); } diff --git a/firestore/src/android/transaction_options_builder_android.h b/firestore/src/android/transaction_options_builder_android.h index 708cce2da5..68ce1cfb1a 100644 --- a/firestore/src/android/transaction_options_builder_android.h +++ b/firestore/src/android/transaction_options_builder_android.h @@ -32,7 +32,8 @@ class TransactionOptionsBuilderInternal : public jni::Object { static jni::Local Create(jni::Env&); - jni::Local SetMaxAttempts(jni::Env&, int32_t max_attempts) const; + jni::Local SetMaxAttempts( + jni::Env&, int32_t max_attempts) const; jni::Local Build(jni::Env&) const; }; From 8b42f3102c89af7dbb430ebbd2b94d293eb75d14 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 14:34:41 -0400 Subject: [PATCH 30/47] Revert "DO NOT MERGE: local build optimizations to build.gradle and gradle.properties and settings.gradle" This reverts commit 809a98fff03225c7c700f220951a001afd281d5e. --- firestore/integration_test_internal/build.gradle | 2 -- .../integration_test_internal/gradle.properties | 1 - settings.gradle | 15 ++++++++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) delete mode 100644 firestore/integration_test_internal/gradle.properties diff --git a/firestore/integration_test_internal/build.gradle b/firestore/integration_test_internal/build.gradle index 1edc7c2606..25113987cf 100644 --- a/firestore/integration_test_internal/build.gradle +++ b/firestore/integration_test_internal/build.gradle @@ -60,8 +60,6 @@ android { versionName '1.0' externalNativeBuild.cmake { arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir" - abiFilters 'x86_64' - targets 'firebase_firestore', 'firebase_auth', 'android_integration_test_main' } multiDexEnabled true } diff --git a/firestore/integration_test_internal/gradle.properties b/firestore/integration_test_internal/gradle.properties deleted file mode 100644 index 3b275c45cf..0000000000 --- a/firestore/integration_test_internal/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -systemProp.firebase_cpp_sdk.dir=/home/dconeybe/dev/firebase/cpp diff --git a/settings.gradle b/settings.gradle index 834f51e0e3..07828daea2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,7 +3,20 @@ include ':app', ':app:app_resources', ':app:google_api_resources', ':app:invites_resources', + ':admob', + ':admob:admob_resources', + ':analytics', ':auth', ':auth:auth_resources', + ':database', + ':database:database_resources', + ':dynamic_links', ':firestore', - ':firestore:firestore_resources' + ':firestore:firestore_resources', + ':functions', + ':installations', + ':messaging', + ':messaging:messaging_java', + ':remote_config', + ':storage', + ':storage:storage_resources' \ No newline at end of file From d7ffb8172e89053de6f32c9ad6fd1dd8669bb1e8 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 14:34:48 -0400 Subject: [PATCH 31/47] Revert "DO NOT MERGE: Android/firebase_dependencies.gradle: use snapshot version of firestore" This reverts commit 0fe44d987976d2475cd97edea27a4692b739c466. --- Android/firebase_dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android/firebase_dependencies.gradle b/Android/firebase_dependencies.gradle index e2122b2333..11424af0c0 100644 --- a/Android/firebase_dependencies.gradle +++ b/Android/firebase_dependencies.gradle @@ -24,7 +24,7 @@ def firebaseDependenciesMap = [ 'auth' : ['com.google.firebase:firebase-auth:21.0.3'], 'database' : ['com.google.firebase:firebase-database:20.0.5'], 'dynamic_links' : ['com.google.firebase:firebase-dynamic-links:21.0.1'], - 'firestore' : ['com.google.firebase:firebase-firestore:24.1.3-SNAPSHOT'], + 'firestore' : ['com.google.firebase:firebase-firestore:24.1.2'], 'functions' : ['com.google.firebase:firebase-functions:20.1.0'], 'installations' : ['com.google.firebase:firebase-installations:17.0.1'], 'invites' : ['com.google.firebase:firebase-invites:17.0.0'], From 61d6ff9046d648a92fc12fbe69d7896c478b3125 Mon Sep 17 00:00:00 2001 From: wu-hui <53845758+wu-hui@users.noreply.github.com> Date: Fri, 27 May 2022 18:42:14 +0000 Subject: [PATCH 32/47] Support git longpaths (#967) --- .github/workflows/android.yml | 4 ++++ .github/workflows/desktop.yml | 4 ++++ .github/workflows/integration_tests.yml | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 4319f65af6..2ce73c1662 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -62,6 +62,10 @@ jobs: git config --global credential.helper 'store --file /tmp/git-credentials' echo 'https://${{ github.token }}@github.com' > /tmp/git-credentials + - name: Enable Git Long-paths Support + if: runner.os == 'Windows' + run: git config --system core.longpaths true + - name: Check expanded matrix config if: github.event.inputs.expanded_matrix == '1' run: | diff --git a/.github/workflows/desktop.yml b/.github/workflows/desktop.yml index 5ab4c7089a..87e7ed7622 100644 --- a/.github/workflows/desktop.yml +++ b/.github/workflows/desktop.yml @@ -101,6 +101,10 @@ jobs: git config --global credential.helper 'store --file /tmp/git-credentials' echo 'https://${{ github.token }}@github.com' > /tmp/git-credentials + - name: Enable Git Long-paths Support + if: runner.os == 'Windows' + run: git config --system core.longpaths true + - name: Setup Xcode version (macos) if: runner.os == 'macOS' run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode_version }}.app/Contents/Developer diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index 83c00e4ae3..cb3bf1f4b1 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -277,6 +277,9 @@ jobs: run: | git config --global credential.helper 'store --file /tmp/git-credentials' echo 'https://${{ github.token }}@github.com' > /tmp/git-credentials + - name: Enable Git Long-paths Support + if: runner.os == 'Windows' + run: git config --system core.longpaths true - name: Set env vars (Linux) if: startsWith(matrix.os, 'ubuntu') run: echo "VCPKG_TRIPLET=x64-linux" >> $GITHUB_ENV @@ -471,6 +474,9 @@ jobs: run: | git config --global credential.helper 'store --file /tmp/git-credentials' echo 'https://${{ github.token }}@github.com' > /tmp/git-credentials + - name: Enable Git Long-paths Support + if: runner.os == 'Windows' + run: git config --system core.longpaths true - name: Add msbuild to PATH (Windows) if: startsWith(matrix.os, 'windows') uses: microsoft/setup-msbuild@v1.0.2 From 2a481ec0dd272d304bb89d7d09b64837df478050 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 27 May 2022 15:37:10 -0400 Subject: [PATCH 33/47] firestore.cmake: update pinned commit to HEAD, now that the fixes in that repo have been merged into master --- cmake/external/firestore.cmake | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index ea5171a9d3..0527638c53 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -37,11 +37,8 @@ function(GetReleasedDep) DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} GIT_REPOSITORY "https://github.com/firebase/firebase-ios-sdk.git" - # Pinned commit in https://github.com/firebase/firebase-ios-sdk/pull/9851 which fixes a - # problematic usage of designated initialization. This commit also includes - # https://github.com/firebase/firebase-ios-sdk/pull/9847, which fixes a problematic bug in - # python_setup.cmake. - GIT_TAG f2fb419cd3332ac74be0a7076841b2162a96060d + # Pinned HEAD commit as of May 27, 2022 @ 15:36 EDT. + GIT_TAG c2bc549a7017c456a20ee69ca7ec27ea4a6077bd PREFIX ${PROJECT_BINARY_DIR} From 188009398ea744a2e0cff33fe1b418dd590ff26e Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Sat, 28 May 2022 05:11:15 +0000 Subject: [PATCH 34/47] integration_tests.yml: explicitly install java so that we get a new enough version to run the firestore emulator --- .github/workflows/integration_tests.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index cb3bf1f4b1..c398f5c327 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -1146,6 +1146,11 @@ jobs: uses: actions/setup-node@v2 with: node-version: 14.x + - name: Setup java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' - name: Setup Firestore Emulator if: steps.get-device-type.outputs.device_type == 'virtual' && contains(needs.check_and_prepare.outputs.apis, 'firestore') run: | @@ -1251,6 +1256,11 @@ jobs: uses: actions/setup-node@v2 with: node-version: 14.x + - name: Setup java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' - name: Setup Firestore Emulator if: steps.get-device-type.outputs.device_type == 'virtual' && contains(needs.check_and_prepare.outputs.apis, 'firestore') run: | @@ -1350,6 +1360,11 @@ jobs: timeout_minutes: 1 max_attempts: 3 command: pip install -r scripts/gha/requirements.txt + - name: Setup java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' - name: Setup Firestore Emulator if: contains(needs.check_and_prepare.outputs.apis, 'firestore') run: | From a88bcb03bfdb3f3c4060234e27cee3b309ebebd5 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Sat, 28 May 2022 12:10:45 +0000 Subject: [PATCH 35/47] integration_tests.yml: install java 8 for the test run, overriding java 11 previously installed for the Firestore emulator --- .github/workflows/integration_tests.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index c398f5c327..cd872016f5 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -1146,7 +1146,7 @@ jobs: uses: actions/setup-node@v2 with: node-version: 14.x - - name: Setup java + - name: Setup java 17 (for Firestore emulator) uses: actions/setup-java@v3 with: distribution: 'temurin' @@ -1156,6 +1156,11 @@ jobs: run: | npm install -g firebase-tools firebase emulators:start --only firestore --project demo-example & + - name: Setup java 8 (for running the tests) + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '8' - name: Run Android integration tests on Emulator locally timeout-minutes: 120 if: steps.get-device-type.outputs.device_type == 'virtual' From ea317463a0c954833dc92ba1458e95882470e9d2 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 30 May 2022 05:23:09 +0000 Subject: [PATCH 36/47] leveldb.cmake: add URL_HASH to improve security --- cmake/external/leveldb.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/external/leveldb.cmake b/cmake/external/leveldb.cmake index 18970659a4..a8a154bb4e 100644 --- a/cmake/external/leveldb.cmake +++ b/cmake/external/leveldb.cmake @@ -26,6 +26,7 @@ ExternalProject_Add( DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} DOWNLOAD_NAME leveldb-${version}.tar.gz URL https://github.com/google/leveldb/archive/${version}.tar.gz + URL_HASH SHA256=9a37f8a6174f09bd622bc723b55881dc541cd50747cbd08831c2a82d620f6d76 PREFIX ${PROJECT_BINARY_DIR} From 0848e7a866a84feb17b4edd1b11e8484a561d46e Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 30 May 2022 16:54:31 +0000 Subject: [PATCH 37/47] Revert "bundle_test.cc: disable ALL of the tests" This reverts commit f8e38b1862f3d0f9adb06b6591bcce57a2293b2f. --- .../src/bundle_test.cc | 30 ++----------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/firestore/integration_test_internal/src/bundle_test.cc b/firestore/integration_test_internal/src/bundle_test.cc index 3cc1ee5be4..d1b5980073 100644 --- a/firestore/integration_test_internal/src/bundle_test.cc +++ b/firestore/integration_test_internal/src/bundle_test.cc @@ -142,9 +142,6 @@ class BundleTest : public FirestoreIntegrationTest { }; TEST_F(BundleTest, CanLoadBundlesWithoutProgressUpdates) { - GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " - "Actions and needs to be investigated (b/233751585)"; - Firestore* db = TestFirestore(); auto bundle = CreateTestBundle(db); @@ -155,9 +152,6 @@ TEST_F(BundleTest, CanLoadBundlesWithoutProgressUpdates) { } TEST_F(BundleTest, CanLoadBundlesWithProgressUpdates) { - GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " - "Actions and needs to be investigated (b/233751585)"; - Firestore* db = TestFirestore(); auto bundle = CreateTestBundle(db); @@ -186,9 +180,6 @@ TEST_F(BundleTest, CanLoadBundlesWithProgressUpdates) { } TEST_F(BundleTest, CanDeleteFirestoreFromProgressUpdate) { - GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " - "Actions and needs to be investigated (b/233751585)"; - Firestore* db = TestFirestore(); auto bundle = CreateTestBundle(db); @@ -225,9 +216,6 @@ TEST_F(BundleTest, CanDeleteFirestoreFromProgressUpdate) { } TEST_F(BundleTest, LoadBundlesForASecondTimeSkips) { - GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " - "Actions and needs to be investigated (b/233751585)"; - // TODO(wuandy): This test fails on Windows CI, but // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; @@ -256,9 +244,6 @@ TEST_F(BundleTest, LoadBundlesForASecondTimeSkips) { } TEST_F(BundleTest, LoadInvalidBundlesShouldFail) { - GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " - "Actions and needs to be investigated (b/233751585)"; - // TODO(wuandy): This test fails on Windows CI, but // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; @@ -288,13 +273,13 @@ TEST_F(BundleTest, LoadInvalidBundlesShouldFail) { } TEST_F(BundleTest, LoadBundleWithDocumentsAlreadyPulledFromBackend) { - GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " - "Actions and needs to be investigated (b/233751585)"; - // TODO(wuandy, b/189477267): This test fails on Windows CI, but // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; + GTEST_SKIP() << "This test fails often on Android and iOS in GitHub Actions " + "and needs to be investigated (b/233751585)"; + Firestore* db = TestFirestore(); auto collection = db->Collection("coll-1"); WriteDocuments(collection, @@ -337,9 +322,6 @@ TEST_F(BundleTest, LoadBundleWithDocumentsAlreadyPulledFromBackend) { } TEST_F(BundleTest, LoadedDocumentsShouldNotBeGarbageCollectedRightAway) { - GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " - "Actions and needs to be investigated (b/233751585)"; - // TODO(wuandy, b/189477267): This test fails on Windows CI, but // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; @@ -364,9 +346,6 @@ TEST_F(BundleTest, LoadedDocumentsShouldNotBeGarbageCollectedRightAway) { } TEST_F(BundleTest, LoadDocumentsFromOtherProjectsShouldFail) { - GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " - "Actions and needs to be investigated (b/233751585)"; - Firestore* db = TestFirestore(); auto bundle = CreateBundle("other-project"); std::vector progresses; @@ -387,9 +366,6 @@ TEST_F(BundleTest, LoadDocumentsFromOtherProjectsShouldFail) { } TEST_F(BundleTest, GetInvalidNamedQuery) { - GTEST_SKIP() << "Bundle tests fails often on Android and iOS in GitHub " - "Actions and needs to be investigated (b/233751585)"; - Firestore* db = TestFirestore(); { auto future = db->NamedQuery("DOES_NOT_EXIST"); From 14b574ae28943b89e2d7c0b1fd53c42515af7489 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 30 May 2022 16:54:59 +0000 Subject: [PATCH 38/47] Revert "cherry-pick bundle_test.cc: Disable LoadBundleWithDocumentsAlreadyPulledFromBackend (https://github.com/firebase/firebase-cpp-sdk/pull/972)" This reverts commit b39452a83d80216e9be5b2d201cc0c8578e99407. --- firestore/integration_test_internal/src/bundle_test.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/firestore/integration_test_internal/src/bundle_test.cc b/firestore/integration_test_internal/src/bundle_test.cc index d1b5980073..3ac9760a9f 100644 --- a/firestore/integration_test_internal/src/bundle_test.cc +++ b/firestore/integration_test_internal/src/bundle_test.cc @@ -277,9 +277,6 @@ TEST_F(BundleTest, LoadBundleWithDocumentsAlreadyPulledFromBackend) { // local run is fine. We need to figure out why and re-enable it. SKIP_TEST_ON_WINDOWS; - GTEST_SKIP() << "This test fails often on Android and iOS in GitHub Actions " - "and needs to be investigated (b/233751585)"; - Firestore* db = TestFirestore(); auto collection = db->Collection("coll-1"); WriteDocuments(collection, From de7a6cd39dfeb87993b6cdf5a413350a83ffc6ff Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 30 May 2022 23:03:18 -0400 Subject: [PATCH 39/47] firestore.cmake: pin to the head commit of the master branch, now that https://github.com/firebase/firebase-ios-sdk/pull/9838 has been merged --- cmake/external/firestore.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index 761cb0a146..be1f8ada36 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -36,10 +36,10 @@ function(GetReleasedDep) firestore DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} - # Pin to the HEAD commit of https://github.com/firebase/firebase-ios-sdk/pull/9838 - # (Firestore TransactionOptions added, to specify maxAttempts) + # Pin to a HEAD commit of the master branch of the firebase-ios-sdk, now that + # https://github.com/firebase/firebase-ios-sdk/pull/9838 has been merged. GIT_REPOSITORY https://github.com/firebase/firebase-ios-sdk.git - GIT_TAG 141fdcb6c3b1efad19708f77ec88a5516c786d8b + GIT_TAG 585b4c83dbeca3e25895ae2f0d2ed7056b3cac7b PREFIX ${PROJECT_BINARY_DIR} From 1dfa36f6cf544ead3722af1e5a2d93b3f6c1f5c8 Mon Sep 17 00:00:00 2001 From: firebase-workflow-trigger-bot Date: Tue, 31 May 2022 18:38:07 +0000 Subject: [PATCH 40/47] Update iOS dependencies - Tue May 31 2022 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### iOS - Firebase/Analytics → 9.1.0 - Firebase/Auth → 9.1.0 - Firebase/Core → 9.1.0 - Firebase/Crashlytics → 9.1.0 - Firebase/Database → 9.1.0 - Firebase/DynamicLinks → 9.1.0 - Firebase/Firestore → 9.1.0 - Firebase/Functions → 9.1.0 - Firebase/Installations → 9.1.0 - Firebase/Messaging → 9.1.0 - Firebase/RemoteConfig → 9.1.0 - Firebase/Storage → 9.1.0 > Created by [Update Android and iOS dependencies workflow](https://github.com/firebase/firebase-cpp-sdk/actions/runs/2416912624). --- admob/integration_test/Podfile | 2 +- analytics/integration_test/Podfile | 4 +- analytics/ios_headers/FIREventNames.h | 2 +- analytics/ios_headers/FIRParameterNames.h | 2 +- analytics/ios_headers/FIRUserPropertyNames.h | 2 +- app/integration_test/Podfile | 2 +- auth/integration_test/Podfile | 4 +- cmake/external/firestore.cmake | 2 +- database/integration_test/Podfile | 8 +- dynamic_links/integration_test/Podfile | 2 +- firestore/integration_test/Podfile | 8 +- firestore/integration_test_internal/Podfile | 8 +- functions/integration_test/Podfile | 8 +- installations/integration_test/Podfile | 4 +- ios_pod/Podfile | 24 +- .../FirebaseAnalyticsSwift-Swift.h | 2 +- .../FirebaseCoreInternal-Swift.h | 2 +- .../FirebaseDatabaseSwift-Swift.h | 2 +- .../FirebaseFirestoreSwift-Swift.h | 2 +- .../swift_headers/FirebaseFunctions-Swift.h | 95 ++-- .../FirebaseInAppMessagingSwift-Swift.h | 2 +- .../FirebaseMLModelDownloader-Swift.h | 2 +- .../FirebaseRemoteConfigSwift-Swift.h | 2 +- .../swift_headers/FirebaseSharedSwift-Swift.h | 2 +- ios_pod/swift_headers/FirebaseStorage-Swift.h | 444 +++++++++++------- ios_pod/swift_headers/SwiftProtobuf-Swift.h | 2 +- messaging/integration_test/Podfile | 4 +- release_build_files/readme.md | 60 +-- remote_config/integration_test/Podfile | 4 +- storage/integration_test/Podfile | 8 +- 30 files changed, 424 insertions(+), 291 deletions(-) diff --git a/admob/integration_test/Podfile b/admob/integration_test/Podfile index edbea91cff..82cd92953b 100644 --- a/admob/integration_test/Podfile +++ b/admob/integration_test/Podfile @@ -4,7 +4,7 @@ platform :ios, '10.0' use_frameworks! :linkage => :static target 'integration_test' do - pod 'Firebase/Analytics', '9.0.0' + pod 'Firebase/Analytics', '9.1.0' pod 'Google-Mobile-Ads-SDK', '7.69.0-cppsdk2' end diff --git a/analytics/integration_test/Podfile b/analytics/integration_test/Podfile index e6e0602e99..3790ca6ddd 100644 --- a/analytics/integration_test/Podfile +++ b/analytics/integration_test/Podfile @@ -5,12 +5,12 @@ use_frameworks! :linkage => :static target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Analytics', '9.0.0' + pod 'Firebase/Analytics', '9.1.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Analytics', '9.0.0' + pod 'Firebase/Analytics', '9.1.0' end post_install do |installer| diff --git a/analytics/ios_headers/FIREventNames.h b/analytics/ios_headers/FIREventNames.h index e26a2cff27..202f81022c 100644 --- a/analytics/ios_headers/FIREventNames.h +++ b/analytics/ios_headers/FIREventNames.h @@ -1,6 +1,6 @@ // Copyright 2022 Google LLC -// Copied from Firebase Analytics iOS SDK 9.0.0. +// Copied from Firebase Analytics iOS SDK 9.1.0. /// @file FIREventNames.h /// diff --git a/analytics/ios_headers/FIRParameterNames.h b/analytics/ios_headers/FIRParameterNames.h index ebeff1e2b4..136f0f5d85 100644 --- a/analytics/ios_headers/FIRParameterNames.h +++ b/analytics/ios_headers/FIRParameterNames.h @@ -1,6 +1,6 @@ // Copyright 2022 Google LLC -// Copied from Firebase Analytics iOS SDK 9.0.0. +// Copied from Firebase Analytics iOS SDK 9.1.0. /// @file FIRParameterNames.h /// diff --git a/analytics/ios_headers/FIRUserPropertyNames.h b/analytics/ios_headers/FIRUserPropertyNames.h index 63e56d0d07..f1c7f267dd 100644 --- a/analytics/ios_headers/FIRUserPropertyNames.h +++ b/analytics/ios_headers/FIRUserPropertyNames.h @@ -1,6 +1,6 @@ // Copyright 2022 Google LLC -// Copied from Firebase Analytics iOS SDK 9.0.0. +// Copied from Firebase Analytics iOS SDK 9.1.0. /// @file FIRUserPropertyNames.h /// diff --git a/app/integration_test/Podfile b/app/integration_test/Podfile index 9e4cc47b75..2b6d6dd224 100644 --- a/app/integration_test/Podfile +++ b/app/integration_test/Podfile @@ -4,7 +4,7 @@ platform :ios, '10.0' use_frameworks! :linkage => :static target 'integration_test' do - pod 'Firebase/Analytics', '9.0.0' + pod 'Firebase/Analytics', '9.1.0' end post_install do |installer| diff --git a/auth/integration_test/Podfile b/auth/integration_test/Podfile index 11c1bd78b9..b08f1f8862 100644 --- a/auth/integration_test/Podfile +++ b/auth/integration_test/Podfile @@ -4,12 +4,12 @@ use_frameworks! :linkage => :static target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Auth', '9.1.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Auth', '9.1.0' end post_install do |installer| diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index 7cb97c0ce9..d6a2849d02 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -20,7 +20,7 @@ endif() # If the format of the line below changes, then be sure to update # https://github.com/firebase/firebase-cpp-sdk/blob/fd054fa016/.github/workflows/update-dependencies.yml#L81 -set(version CocoaPods-9.0.0) +set(version CocoaPods-9.1.0) function(GetReleasedDep) message("Getting released firebase-ios-sdk @ ${version}") diff --git a/database/integration_test/Podfile b/database/integration_test/Podfile index 8f77c1dcfe..0f48f8d03a 100644 --- a/database/integration_test/Podfile +++ b/database/integration_test/Podfile @@ -4,14 +4,14 @@ use_frameworks! :linkage => :static target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Database', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Database', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Database', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Database', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end post_install do |installer| diff --git a/dynamic_links/integration_test/Podfile b/dynamic_links/integration_test/Podfile index 331ebe65f4..7141ef86bc 100644 --- a/dynamic_links/integration_test/Podfile +++ b/dynamic_links/integration_test/Podfile @@ -4,7 +4,7 @@ platform :ios, '10.0' use_frameworks! :linkage => :static target 'integration_test' do - pod 'Firebase/DynamicLinks', '9.0.0' + pod 'Firebase/DynamicLinks', '9.1.0' end post_install do |installer| diff --git a/firestore/integration_test/Podfile b/firestore/integration_test/Podfile index a730b4ebc9..d106fbcf81 100644 --- a/firestore/integration_test/Podfile +++ b/firestore/integration_test/Podfile @@ -4,14 +4,14 @@ use_frameworks! :linkage => :static target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Firestore', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Firestore', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Firestore', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Firestore', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end post_install do |installer| diff --git a/firestore/integration_test_internal/Podfile b/firestore/integration_test_internal/Podfile index 07c1d44ed3..86c2bec605 100644 --- a/firestore/integration_test_internal/Podfile +++ b/firestore/integration_test_internal/Podfile @@ -4,14 +4,14 @@ use_frameworks! :linkage => :static target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Firestore', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Firestore', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Firestore', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Firestore', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end post_install do |installer| diff --git a/functions/integration_test/Podfile b/functions/integration_test/Podfile index 90e41cc6db..c843f66614 100644 --- a/functions/integration_test/Podfile +++ b/functions/integration_test/Podfile @@ -4,14 +4,14 @@ use_frameworks! :linkage => :static target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Functions', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Functions', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Functions', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Functions', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end post_install do |installer| diff --git a/installations/integration_test/Podfile b/installations/integration_test/Podfile index 74b8df6af9..1329967794 100644 --- a/installations/integration_test/Podfile +++ b/installations/integration_test/Podfile @@ -4,8 +4,8 @@ platform :ios, '10.0' use_frameworks! :linkage => :static target 'integration_test' do - pod 'Firebase/Analytics', '9.0.0' - pod 'Firebase/Installations', '9.0.0' + pod 'Firebase/Analytics', '9.1.0' + pod 'Firebase/Installations', '9.1.0' end post_install do |installer| diff --git a/ios_pod/Podfile b/ios_pod/Podfile index 27dacad454..b5a4597ac2 100644 --- a/ios_pod/Podfile +++ b/ios_pod/Podfile @@ -3,19 +3,19 @@ platform :ios, '10.0' use_frameworks! target 'GetPods' do - pod 'Firebase/Core', '9.0.0' + pod 'Firebase/Core', '9.1.0' pod 'Google-Mobile-Ads-SDK', '7.69.0-cppsdk2' - pod 'Firebase/Analytics', '9.0.0' - pod 'Firebase/Auth', '9.0.0' - pod 'Firebase/Crashlytics', '9.0.0' - pod 'Firebase/Database', '9.0.0' - pod 'Firebase/DynamicLinks', '9.0.0' - pod 'Firebase/Firestore', '9.0.0' - pod 'Firebase/Functions', '9.0.0' - pod 'Firebase/Installations', '9.0.0' - pod 'Firebase/Messaging', '9.0.0' - pod 'Firebase/RemoteConfig', '9.0.0' - pod 'Firebase/Storage', '9.0.0' + pod 'Firebase/Analytics', '9.1.0' + pod 'Firebase/Auth', '9.1.0' + pod 'Firebase/Crashlytics', '9.1.0' + pod 'Firebase/Database', '9.1.0' + pod 'Firebase/DynamicLinks', '9.1.0' + pod 'Firebase/Firestore', '9.1.0' + pod 'Firebase/Functions', '9.1.0' + pod 'Firebase/Installations', '9.1.0' + pod 'Firebase/Messaging', '9.1.0' + pod 'Firebase/RemoteConfig', '9.1.0' + pod 'Firebase/Storage', '9.1.0' end diff --git a/ios_pod/swift_headers/FirebaseAnalyticsSwift-Swift.h b/ios_pod/swift_headers/FirebaseAnalyticsSwift-Swift.h index 76fd043d2b..ca90341c73 100644 --- a/ios_pod/swift_headers/FirebaseAnalyticsSwift-Swift.h +++ b/ios_pod/swift_headers/FirebaseAnalyticsSwift-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 // clang-1316.0.20.8) diff --git a/ios_pod/swift_headers/FirebaseCoreInternal-Swift.h b/ios_pod/swift_headers/FirebaseCoreInternal-Swift.h index 5ae00c0918..8ed11a3e85 100644 --- a/ios_pod/swift_headers/FirebaseCoreInternal-Swift.h +++ b/ios_pod/swift_headers/FirebaseCoreInternal-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8) #ifndef FIREBASECOREINTERNAL_SWIFT_H diff --git a/ios_pod/swift_headers/FirebaseDatabaseSwift-Swift.h b/ios_pod/swift_headers/FirebaseDatabaseSwift-Swift.h index cc934567d5..ebc49239ed 100644 --- a/ios_pod/swift_headers/FirebaseDatabaseSwift-Swift.h +++ b/ios_pod/swift_headers/FirebaseDatabaseSwift-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 // clang-1316.0.20.8) diff --git a/ios_pod/swift_headers/FirebaseFirestoreSwift-Swift.h b/ios_pod/swift_headers/FirebaseFirestoreSwift-Swift.h index 52337a1afb..49a83129fd 100644 --- a/ios_pod/swift_headers/FirebaseFirestoreSwift-Swift.h +++ b/ios_pod/swift_headers/FirebaseFirestoreSwift-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 // clang-1316.0.20.8) diff --git a/ios_pod/swift_headers/FirebaseFunctions-Swift.h b/ios_pod/swift_headers/FirebaseFunctions-Swift.h index 5e5cb93f94..77640fee74 100644 --- a/ios_pod/swift_headers/FirebaseFunctions-Swift.h +++ b/ios_pod/swift_headers/FirebaseFunctions-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8) #ifndef FIREBASEFUNCTIONS_SWIFT_H @@ -236,41 +236,73 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); /// Functions is the client for Cloud Functions for a Firebase project. SWIFT_CLASS_NAMED("Functions") @interface FIRFunctions : NSObject -/// Creates a Cloud Functions client or returns a pre-existing instance if it already exists. +/// Creates a Cloud Functions client using the default or returns a pre-existing instance if it +/// already exists. +/// +/// returns: +/// A shared Functions instance initialized with the default FirebaseApp. + (FIRFunctions* _Nonnull)functions SWIFT_WARN_UNUSED_RESULT; /// Creates a Cloud Functions client with the given app, or returns a pre-existing /// instance if one already exists. -/// @param app The app for the Firebase project. +/// \param app The app for the Firebase project. +/// +/// +/// returns: +/// A shared Functions instance initialized with the specified FirebaseApp. + (FIRFunctions* _Nonnull)functionsForApp:(FIRApp* _Nonnull)app SWIFT_WARN_UNUSED_RESULT; /// Creates a Cloud Functions client with the default app and given region. -/// @param region The region for the http trigger, such as “us-central1”. +/// \param region The region for the HTTP trigger, such as us-central1. +/// +/// +/// returns: +/// A shared Functions instance initialized with the default FirebaseApp and a custom +/// region. + (FIRFunctions* _Nonnull)functionsForRegion:(NSString* _Nonnull)region SWIFT_WARN_UNUSED_RESULT; /// Creates a Cloud Functions client with the given app and region, or returns a pre-existing /// instance if one already exists. -/// @param customDomain A custom domain for the http trigger, such as “https://mydomain.com”. +/// \param customDomain A custom domain for the HTTP trigger, such as “https //mydomain.com”. +/// +/// +/// returns: +/// A shared Functions instance initialized with the default FirebaseApp and a custom +/// HTTP trigger domain. + (FIRFunctions* _Nonnull)functionsForCustomDomain:(NSString* _Nonnull)customDomain SWIFT_WARN_UNUSED_RESULT; /// Creates a Cloud Functions client with the given app and region, or returns a pre-existing /// instance if one already exists. -/// @param app The app for the Firebase project. -/// @param region The region for the http trigger, such as “us-central1”. +/// \param app The app for the Firebase project. +/// +/// \param region The region for the HTTP trigger, such as us-central1. +/// +/// +/// returns: +/// An instance of Functions with a custom app and region. + (FIRFunctions* _Nonnull)functionsForApp:(FIRApp* _Nonnull)app region:(NSString* _Nonnull)region SWIFT_WARN_UNUSED_RESULT; /// Creates a Cloud Functions client with the given app and region, or returns a pre-existing /// instance if one already exists. -/// @param app The app for the Firebase project. -/// @param customDomain A custom domain for the http trigger, such as “https://mydomain.com”. +/// \param app The app for the Firebase project. +/// +/// \param customDomain A custom domain for the HTTP trigger, such as +/// https://mydomain.com. +/// +/// +/// returns: +/// An instance of Functions with a custom app and HTTP trigger domain. + (FIRFunctions* _Nonnull)functionsForApp:(FIRApp* _Nonnull)app customDomain:(NSString* _Nonnull)customDomain SWIFT_WARN_UNUSED_RESULT; /// Creates a reference to the Callable HTTPS trigger with the given name. -/// @param name The name of the Callable HTTPS trigger. +/// \param name The name of the Callable HTTPS trigger. +/// - (FIRHTTPSCallable* _Nonnull)HTTPSCallableWithName:(NSString* _Nonnull)name SWIFT_WARN_UNUSED_RESULT; - (FIRHTTPSCallable* _Nonnull)HTTPSCallableWithURL:(NSURL* _Nonnull)url SWIFT_WARN_UNUSED_RESULT; /// Changes this instance to point to a Cloud Functions emulator running locally. /// See https://firebase.google.com/docs/functions/local-emulator -/// @param host The host of the local emulator, such as “localhost”. -/// @param port The port of the local emulator, for example 5005. +/// \param host The host of the local emulator, such as “localhost”. +/// +/// \param port The port of the local emulator, for example 5005. +/// - (void)useEmulatorWithHost:(NSString* _Nonnull)host port:(NSInteger)port; - (nonnull instancetype)init SWIFT_UNAVAILABLE; + (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); @@ -332,7 +364,7 @@ typedef SWIFT_ENUM_NAMED(NSInteger, FIRFunctionsErrorCode, "FunctionsErrorCode", @class FIRHTTPSCallableResult; -/// A HTTPSCallable is reference to a particular Callable HTTPS trigger in Cloud +/// A HTTPSCallable is a reference to a particular Callable HTTPS trigger in Cloud /// Functions. SWIFT_CLASS_NAMED("HTTPSCallable") @interface FIRHTTPSCallable : NSObject @@ -342,19 +374,19 @@ SWIFT_CLASS_NAMED("HTTPSCallable") /// The data passed into the trigger can be any of the following types: ///
    ///
  • -/// NSNull +/// nil or NSNull ///
  • ///
  • -/// NSString +/// String ///
  • ///
  • -/// NSNumber +/// NSNumber, or any Swift numeric type bridgeable to NSNumber ///
  • ///
  • -/// NSArray, where the contained objects are also one of these types. +/// [Any], where the contained objects are also one of these types. ///
  • ///
  • -/// NSDictionary, where the values are also one of these types. +/// [String: Any] where the values are also one of these types. ///
  • ///
/// The request to the Cloud Functions backend made by this method automatically includes a @@ -363,19 +395,22 @@ SWIFT_CLASS_NAMED("HTTPSCallable") /// Firebase Cloud Messaging sends data to the Firebase backend periodically to collect information /// regarding the app instance. To stop this, see Messaging.deleteData(). It /// resumes with a new FCM Token the next time you call this method. -/// @param data Parameters to pass to the trigger. -/// @param completion The block to call when the HTTPS request has completed. +/// \param data Parameters to pass to the trigger. +/// +/// \param completion The block to call when the HTTPS request has completed. +/// - (void)callWithObject:(id _Nullable)data completion: (void (^_Nonnull)(FIRHTTPSCallableResult* _Nullable, NSError* _Nullable))completion; -/// Executes this Callable HTTPS trigger asynchronously. This API should only be used from Objective -/// C The request to the Cloud Functions backend made by this method automatically includes a -/// Firebase Installations ID token to identify the app instance. If a user is logged in with -/// Firebase Auth, an auth ID token for the user is also automatically included. -/// Firebase Cloud Messaging sends data to the Firebase backend periodically to collect information -/// regarding the app instance. To stop this, see Messaging.deleteData(). It -/// resumes with a new FCM Token the next time you call this method. -/// @param completion The block to call when the HTTPS request has completed. +/// Executes this Callable HTTPS trigger asynchronously. This API should only be used from +/// Objective-C. The request to the Cloud Functions backend made by this method automatically +/// includes a Firebase Installations ID token to identify the app instance. If a user is logged in +/// with Firebase Auth, an auth ID token for the user is also automatically included. Firebase Cloud +/// Messaging sends data to the Firebase backend periodically to collect information regarding the +/// app instance. To stop this, see Messaging.deleteData(). It resumes with a new FCM +/// Token the next time you call this method. \param completion The block to call when the HTTPS +/// request has completed. +/// - (void)callWithCompletion:(void (^_Nonnull)(FIRHTTPSCallableResult* _Nullable, NSError* _Nullable))completion; - (nonnull instancetype)init SWIFT_UNAVAILABLE; @@ -387,8 +422,8 @@ SWIFT_CLASS_NAMED("HTTPSCallableResult") @interface FIRHTTPSCallableResult : NSObject /// The data that was returned from the Callable HTTPS trigger. /// The data is in the form of native objects. For example, if your trigger returned an -/// array, this object would be an NSArray. If your trigger returned a JavaScript object with -/// keys and values, this object would be an NSDictionary. +/// array, this object would be an Array. If your trigger returned a JavaScript +/// object with keys and values, this object would be an instance of [String: Any]. @property(nonatomic, readonly) id _Nonnull data; - (nonnull instancetype)init SWIFT_UNAVAILABLE; + (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); diff --git a/ios_pod/swift_headers/FirebaseInAppMessagingSwift-Swift.h b/ios_pod/swift_headers/FirebaseInAppMessagingSwift-Swift.h index 56528c1416..fd40256f0c 100644 --- a/ios_pod/swift_headers/FirebaseInAppMessagingSwift-Swift.h +++ b/ios_pod/swift_headers/FirebaseInAppMessagingSwift-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 // clang-1316.0.20.8) diff --git a/ios_pod/swift_headers/FirebaseMLModelDownloader-Swift.h b/ios_pod/swift_headers/FirebaseMLModelDownloader-Swift.h index 6340dac319..33256545fd 100644 --- a/ios_pod/swift_headers/FirebaseMLModelDownloader-Swift.h +++ b/ios_pod/swift_headers/FirebaseMLModelDownloader-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 // clang-1316.0.20.8) diff --git a/ios_pod/swift_headers/FirebaseRemoteConfigSwift-Swift.h b/ios_pod/swift_headers/FirebaseRemoteConfigSwift-Swift.h index 7bcdb5bf9f..5aa1f94856 100644 --- a/ios_pod/swift_headers/FirebaseRemoteConfigSwift-Swift.h +++ b/ios_pod/swift_headers/FirebaseRemoteConfigSwift-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 // clang-1316.0.20.8) diff --git a/ios_pod/swift_headers/FirebaseSharedSwift-Swift.h b/ios_pod/swift_headers/FirebaseSharedSwift-Swift.h index 8c5aecf33f..df7978fd00 100644 --- a/ios_pod/swift_headers/FirebaseSharedSwift-Swift.h +++ b/ios_pod/swift_headers/FirebaseSharedSwift-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 // clang-1316.0.20.8) diff --git a/ios_pod/swift_headers/FirebaseStorage-Swift.h b/ios_pod/swift_headers/FirebaseStorage-Swift.h index 36ba28f0d6..3a24d43f41 100644 --- a/ios_pod/swift_headers/FirebaseStorage-Swift.h +++ b/ios_pod/swift_headers/FirebaseStorage-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8) #ifndef FIREBASESTORAGE_SWIFT_H @@ -233,65 +233,97 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); @class FIRApp; @class FIRStorageReference; -/// FirebaseStorage is a service that supports uploading and downloading binary objects, -/// such as images, videos, and other files to Google Cloud Storage. -/// If you call FirebaseStorage.storage(), the instance will initialize with the -/// default FirebaseApp, FirebaseApp.app(), and the storage location will come from the -/// provided GoogleService-Info.plist. If you provide a custom instance of FirebaseApp, the storage -/// location will be specified via the FirebaseOptions#storageBucket property. +/// Firebase Storage is a service that supports uploading and downloading binary objects, +/// such as images, videos, and other files to Google Cloud Storage. Instances of +/// Storage are not thread-safe. If you call Storage.storage(), the +/// instance will initialize with the default FirebaseApp, +/// FirebaseApp.app(), and the storage location will come from the provided +/// GoogleService-Info.plist. +/// If you provide a custom instance of FirebaseApp, +/// the storage location will be specified via the FirebaseOptions.storageBucket +/// property. SWIFT_CLASS_NAMED("Storage") @interface FIRStorage : NSObject -/// An instance of FirebaseStorage, configured with the default FirebaseApp. -/// @return the FirebaseStorage instance, configured with the default FirebaseApp. +/// The default Storage instance. +/// +/// returns: +/// An instance of Storage, configured with the default FirebaseApp. + (FIRStorage *_Nonnull)storage SWIFT_WARN_UNUSED_RESULT; -/// An instance of FirebaseStorage, configured with a custom storage bucket @a url. -/// @param url The gs:// url to your Firebase Storage Bucket. -/// @return the FirebaseStorage instance, configured with the custom FirebaseApp. +/// A method used to create Storage instances initialized with a custom storage bucket +/// URL. Any StorageReferences generated from this instance of Storage +/// will reference files and directories within the specified bucket. \param url The +/// gs:// URL to your Firebase Storage bucket. +/// +/// +/// returns: +/// A Storage instance, configured with the custom storage bucket. + (FIRStorage *_Nonnull)storageWithURL:(NSString *_Nonnull)url SWIFT_WARN_UNUSED_RESULT; -/// Creates an instance of FirebaseStorage, configured with the custom FirebaseApp @a app. -/// @param app The custom FirebaseApp used for initialization. -/// @return the FirebaseStorage instance, configured with the custom FirebaseApp. +/// Creates an instance of Storage, configured with a custom FirebaseApp. +/// StorageReferences generated from a resulting instance will reference files in the +/// Firebase project associated with custom FirebaseApp. \param app The custom +/// FirebaseApp used for initialization. +/// +/// +/// returns: +/// A Storage instance, configured with the custom FirebaseApp. + (FIRStorage *_Nonnull)storageForApp:(FIRApp *_Nonnull)app SWIFT_WARN_UNUSED_RESULT; -/// Creates an instance of FirebaseStorage, configured with a custom FirebaseApp @a app and a custom -/// storage bucket @a url. -/// @param app The custom FirebaseApp used for initialization. -/// @param url The gs:// url to your Firebase Storage Bucket. -/// @return the FirebaseStorage instance, configured with the custom FirebaseApp. +/// Creates an instance of Storage, configured with a custom FirebaseApp +/// and a custom storage bucket URL. \param app The custom FirebaseApp used for +/// initialization. +/// +/// \param url The gs:// url to your Firebase Storage bucket. +/// +/// +/// returns: +/// the Storage instance, configured with the custom FirebaseApp and +/// storage bucket URL. + (FIRStorage *_Nonnull)storageForApp:(FIRApp *_Nonnull)app URL:(NSString *_Nonnull)url SWIFT_WARN_UNUSED_RESULT; -/// The Firebase App associated with this Firebase Storage instance. +/// The FirebaseApp associated with this Storage instance. @property(nonatomic, readonly, strong) FIRApp *_Nonnull app; -/// Maximum time in seconds to retry an upload if a failure occurs. +/// The maximum time in seconds to retry an upload if a failure occurs. /// Defaults to 10 minutes (600 seconds). @property(nonatomic) NSTimeInterval maxUploadRetryTime; -/// Maximum time in seconds to retry a download if a failure occurs. +/// The maximum time in seconds to retry a download if a failure occurs. /// Defaults to 10 minutes (600 seconds). @property(nonatomic) NSTimeInterval maxDownloadRetryTime; -/// Maximum time in seconds to retry operations other than upload and download if a failure occurs. -/// Defaults to 2 minutes (120 seconds). +/// The maximum time in seconds to retry operations other than upload and download if a failure +/// occurs. Defaults to 2 minutes (120 seconds). @property(nonatomic) NSTimeInterval maxOperationRetryTime; -/// Queue that all developer callbacks are fired on. Defaults to the main queue. +/// A DispatchQueue that all developer callbacks are fired on. Defaults to the main +/// queue. @property(nonatomic, strong) dispatch_queue_t _Nonnull callbackQueue; -/// Creates a StorageReference initialized at the root Firebase Storage location. -/// @return An instance of StorageReference initialized at the root. +/// Creates a StorageReference initialized at the root Firebase Storage location. +/// +/// returns: +/// An instance of StorageReference referencing the root of the storage bucket. - (FIRStorageReference *_Nonnull)reference SWIFT_WARN_UNUSED_RESULT; -/// Creates a StorageReference given a gs:// or https:// URL pointing to a Firebase Storage -/// location. For example, you can pass in an https:// download URL retrieved from -/// [StorageReference downloadURLWithCompletion] or the gs:// URI from -/// [StorageReference description]. -/// @param string A gs:// or https:// URL to initialize the reference with. -/// @return An instance of StorageReference at the given child path. -/// @throws Throws an exception if passed in URL is not associated with the FirebaseApp used to -/// initialize this FirebaseStorage. -- (FIRStorageReference *_Nonnull)referenceForURL:(NSString *_Nonnull)string - SWIFT_WARN_UNUSED_RESULT; -/// Creates a StorageReference initialized at a child Firebase Storage location. -/// @param string A relative path from the root to initialize the reference with, +/// Creates a StorageReference given a gs:// or https:// URL pointing to a +/// Firebase Storage location. For example, you can pass in an https:// download URL +/// retrieved from StorageReference.downloadURL(completion:) or the gs:// +/// URL from StorageReference.description. \param url A gs // or https:// URL to +/// initialize the reference with. +/// +/// +/// throws: +/// Throws a fatal error if url is not associated with the FirebaseApp +/// used to initialize this Storage instance. +/// +/// returns: +/// An instance of StorageReference at the given child path. +- (FIRStorageReference *_Nonnull)referenceForURL:(NSString *_Nonnull)url SWIFT_WARN_UNUSED_RESULT; +/// Creates a StorageReference initialized at a location specified by the +/// path parameter. \param path A relative path from the root of the storage bucket, /// for instance @“path/to/object”. -/// @return An instance of StorageReference at the given child path. -- (FIRStorageReference *_Nonnull)referenceWithPath:(NSString *_Nonnull)string +/// +/// +/// returns: +/// An instance of StorageReference pointing to the given path. +- (FIRStorageReference *_Nonnull)referenceWithPath:(NSString *_Nonnull)path SWIFT_WARN_UNUSED_RESULT; /// Configures the Storage SDK to use an emulated backend instead of the default remote backend. +/// This method should be called before invoking any other methods on a new instance of +/// Storage. - (void)useEmulatorWithHost:(NSString *_Nonnull)host port:(NSInteger)port; - (id _Nonnull)copy SWIFT_WARN_UNUSED_RESULT; - (BOOL)isEqual:(id _Nullable)object SWIFT_WARN_UNUSED_RESULT; @@ -312,20 +344,19 @@ SWIFT_PROTOCOL_NAMED("StorageTaskManagement") @optional /// Pauses a task currently in progress. - (void)pause; -/// Pauses a task currently in progress. +/// Cancels a task. - (void)cancel; -/// Pauses a task currently in progress. +/// Resumes a paused task. - (void)resume; @end @class FIRStorageTaskSnapshot; -/// A superclass to all Storage*Tasks, including StorageUploadTask -/// and StorageDownloadTask, to provide state transitions, event raising, and common storage -/// or metadata and errors. -/// Callbacks are always fired on the developer specified callback queue. -/// If no queue is specified by the developer, it defaults to the main queue. -/// Currently not thread safe, so only call methods on the main thread. +/// A superclass to all Storage tasks, including StorageUploadTask +/// and StorageDownloadTask, to provide state transitions, event raising, and common +/// storage for metadata and errors. Callbacks are always fired on the developer-specified callback +/// queue. If no queue is specified, it defaults to the main queue. This class is not thread safe, +/// so only call methods on the main thread. SWIFT_CLASS_NAMED("StorageTask") @interface FIRStorageTask : NSObject /// An immutable view of the task and associated metadata, progress, error, etc. @@ -336,46 +367,52 @@ SWIFT_CLASS_NAMED("StorageTask") enum FIRStorageTaskStatus : NSInteger; -/// Extends FIRStorageTask to provide observable semantics such as adding and removing observers. -/// Observers produce a FIRStorageHandle, which is used to keep track of and remove specific -/// observers at a later date. -/// This class is currently not thread safe and can only be called on the main thread. +/// An extended StorageTask providing observable semantics that can be used for +/// responding to changes in task state. Observers produce a StorageHandle, which is +/// used to keep track of and remove specific observers at a later date. This class is not thread +/// safe and can only be called on the main thread. SWIFT_CLASS_NAMED("StorageObservableTask") @interface FIRStorageObservableTask : FIRStorageTask /// Observes changes in the upload status: Resume, Pause, Progress, Success, and Failure. -/// @param status The StorageTaskStatus change to observe. -/// @param handler A callback that fires every time the status event occurs, -/// returns a StorageTaskSnapshot containing the state of the task. -/// @return A task handle that can be used to remove the observer at a later date. +/// \param status The StorageTaskStatus change to observe. +/// +/// \param handler A callback that fires every time the status event occurs, +/// containing a StorageTaskSnapshot describing task state. +/// +/// +/// returns: +/// A task handle that can be used to remove the observer at a later date. - (NSString *_Nonnull)observeStatus:(enum FIRStorageTaskStatus)status handler:(void (^_Nonnull)(FIRStorageTaskSnapshot *_Nonnull))handler; /// Removes the single observer with the provided handle. -/// @param handle The handle of the task to remove. +/// \param handle The handle of the task to remove. +/// - (void)removeObserverWithHandle:(NSString *_Nonnull)handle; /// Removes all observers for a single status. -/// @param status A StorageTaskStatus to remove listeners for. +/// \param status A StorageTaskStatus to remove all listeners for. +/// - (void)removeAllObserversForStatus:(enum FIRStorageTaskStatus)status; /// Removes all observers. - (void)removeAllObservers; @end -/// StorageDownloadTask implements resumable downloads from an object in Firebase Storage. -/// Downloads can be returned on completion with a completion handler, and can be monitored -/// by attaching observers, or controlled by calling StorageTask#pause, StorageTask#resume, -/// or FIRIMPLStorageTask#cancel. -/// Downloads can currently be returned as Data in memory, or as an URL to a file on disk. -/// Downloads are performed on a background queue, and callbacks are raised on the developer -/// specified callbackQueue in Storage, or the main queue if left unspecified. -/// Currently all uploads must be initiated and managed on the main queue. +/// StorageDownloadTask implements resumable downloads from an object in Firebase +/// Storage. Downloads can be returned on completion with a completion handler, and can be monitored +/// by attaching observers, or controlled by calling pause(), resume(), +/// or cancel(). +/// Downloads can currently be returned as Data in memory, or as a URL to +/// a file on disk. Downloads are performed on a background queue, and callbacks are raised on the +/// developer specified callbackQueue in Storage, or the main queue if left +/// unspecified. Currently all uploads must be initiated and managed on the main queue. SWIFT_CLASS_NAMED("StorageDownloadTask") @interface FIRStorageDownloadTask : FIRStorageObservableTask /// Prepares a task and begins execution. - (void)enqueue; -/// Pauses a task currently in progress. +/// Pauses a task currently in progress. Calling this on a paused task has no effect. - (void)pause; -/// Pauses a task currently in progress. +/// Cancels a task. - (void)cancel; -/// Pauses a task currently in progress. +/// Resumes a paused task. Calling this on a running task has no effect. - (void)resume; @end @@ -397,16 +434,21 @@ typedef SWIFT_ENUM_NAMED(NSInteger, FIRStorageErrorCode, "StorageErrorCode", ope /// Contains the prefixes and items returned by a StorageReference.list() call. SWIFT_CLASS_NAMED("StorageListResult") @interface FIRStorageListResult : NSObject -/// The prefixes (folders) returned by the list() operation. -/// @return A list of prefixes (folders). +/// The prefixes (folders) returned by a list() operation. +/// +/// returns: +/// A list of prefixes (folders). @property(nonatomic, readonly, copy) NSArray *_Nonnull prefixes; -/// Returns a token that can be used to resume a previous list() operation. -/// nil indicates that there are no more results. -/// @return A page token if more results are available. +/// The objects (files) returned by a list() operation. +/// +/// returns: +/// A page token if more results are available. @property(nonatomic, readonly, copy) NSArray *_Nonnull items; /// Returns a token that can be used to resume a previous list() operation. /// nil indicates that there are no more results. -/// @return A page token if more results are available. +/// +/// returns: +/// A page token if more results are available. @property(nonatomic, readonly, copy) NSString *_Nullable pageToken; - (id _Nonnull)copy SWIFT_WARN_UNUSED_RESULT; - (nonnull instancetype)init SWIFT_UNAVAILABLE; @@ -477,35 +519,40 @@ SWIFT_CLASS_NAMED("StorageMetadata") @class FIRStorageUploadTask; @class NSURL; -/// StorageReference represents a reference to a Google Cloud Storage object. Developers can -/// upload and download objects, as well as get/set object metadata, and delete an object at the -/// path. -/// @see https://cloud.google.com/storage/ +/// StorageReference represents a reference to a Google Cloud Storage object. +/// Developers can upload and download objects, as well as get/set object metadata, and delete an +/// object at the path. See the Cloud docs for more details: https://cloud.google.com/storage/ SWIFT_CLASS_NAMED("StorageReference") @interface FIRStorageReference : NSObject -/// The Storage service object which created this reference. +/// The Storage service object which created this reference. @property(nonatomic, readonly, strong) FIRStorage *_Nonnull storage; -/// The name of the Google Cloud Storage bucket associated with this reference, -/// in gs://bucket/path/to/object.txt, the bucket would be: ‘bucket’ +/// The name of the Google Cloud Storage bucket associated with this reference. +/// For example, in gs://bucket/path/to/object.txt, the bucket would be ‘bucket’. @property(nonatomic, readonly, copy) NSString *_Nonnull bucket; /// The full path to this object, not including the Google Cloud Storage bucket. -/// In gs://bucket/path/to/object.txt, the full path would be: ‘path/to/object.txt’ +/// In gs://bucket/path/to/object.txt, the full path would be: +/// path/to/object.txt @property(nonatomic, readonly, copy) NSString *_Nonnull fullPath; -/// The short name of the object associated with this reference, -/// in gs://bucket/path/to/object.txt, the name of the object would be: ‘object.txt’ +/// The short name of the object associated with this reference. +/// In gs://bucket/path/to/object.txt, the name of the object would be +/// object.txt. @property(nonatomic, readonly, copy) NSString *_Nonnull name; -/// Creates a new StorageReference pointing to the root object. -/// @return A new StorageReference pointing to the root object. +/// Creates a new StorageReference pointing to the root object. +/// +/// returns: +/// A new StorageReference pointing to the root object. - (FIRStorageReference *_Nonnull)root SWIFT_WARN_UNUSED_RESULT; -/// Creates a new StorageReference pointing to the parent of the current reference -/// or nil if this instance references the root location. +/// Creates a new StorageReference pointing to the parent of the current reference +/// or nil if this instance references the root location. /// For example: /// path = foo/bar/baz parent = foo/bar /// path = foo parent = (root) /// path = (root) parent = nil -/// @return A new StorageReference pointing to the parent of the current reference. +/// +/// returns: +/// A new StorageReference pointing to the parent of the current reference. - (FIRStorageReference *_Nullable)parent SWIFT_WARN_UNUSED_RESULT; -/// Creates a new StorageReference pointing to a child object of the current reference. +/// Creates a new StorageReference pointing to a child object of the current reference. /// path = foo child = bar newPath = foo/bar /// path = foo/bar child = baz ntask.impl.snapshotwPath = foo/bar/baz /// All leading and trailing slashes will be removed, and consecutive slashes will be @@ -513,141 +560,192 @@ SWIFT_CLASS_NAMED("StorageReference") /// child = /foo/bar newPath = foo/bar /// child = foo/bar/ newPath = foo/bar /// child = foo///bar newPath = foo/bar -/// @param path Path to append to the current path. -/// @return A new StorageReference pointing to a child location of the current reference. +/// \param path The path to append to the current path. +/// +/// +/// returns: +/// A new StorageReference pointing to a child location of the current reference. - (FIRStorageReference *_Nonnull)child:(NSString *_Nonnull)path SWIFT_WARN_UNUSED_RESULT; -/// Asynchronously uploads data to the currently specified StorageReference, +/// Asynchronously uploads data to the currently specified StorageReference, /// without additional metadata. /// This is not recommended for large files, and one should instead upload a file from disk. -/// @param uploadData The Data to upload. -/// @param metadata StorageMetadata containing additional information (MIME type, etc.) +/// \param uploadData The data to upload. +/// +/// \param metadata StorageMetadata containing additional information (MIME type, etc.) /// about the object being uploaded. -/// @return An instance of StorageUploadTask, which can be used to monitor or manage the upload. +/// +/// +/// returns: +/// An instance of StorageUploadTask, which can be used to monitor or manage the +/// upload. - (FIRStorageUploadTask *_Nonnull)putData:(NSData *_Nonnull)uploadData metadata:(FIRStorageMetadata *_Nullable)metadata; -/// Asynchronously uploads data to the currently specified StorageReference. +/// Asynchronously uploads data to the currently specified StorageReference. /// This is not recommended for large files, and one should instead upload a file from disk. -/// @param uploadData The Data to upload. -/// @return An instance of StorageUploadTask, which can be used to monitor or manage the upload. +/// \param uploadData The data to upload. +/// +/// +/// returns: +/// An instance of StorageUploadTask, which can be used to monitor or manage the +/// upload. - (FIRStorageUploadTask *_Nonnull)putData:(NSData *_Nonnull)uploadData; -/// Asynchronously uploads data to the currently specified StorageReference. +/// Asynchronously uploads data to the currently specified StorageReference. /// This is not recommended for large files, and one should instead upload a file from disk. -/// @param uploadData The Data to upload. -/// @param metadata StorageMetadata containing additional information (MIME type, etc.) +/// \param uploadData The data to upload. +/// +/// \param metadata StorageMetadata containing additional information (MIME type, etc.) /// about the object being uploaded. -/// @param completion A completion block that either returns the object metadata on success, +/// +/// \param completion A closure that either returns the object metadata on success, /// or an error on failure. -/// @return An instance of StorageUploadTask, which can be used to monitor or manage the upload. +/// +/// +/// returns: +/// An instance of StorageUploadTask, which can be used to monitor or manage the +/// upload. - (FIRStorageUploadTask *_Nonnull)putData:(NSData *_Nonnull)uploadData metadata:(FIRStorageMetadata *_Nullable)metadata completion:(void (^_Nullable)(FIRStorageMetadata *_Nullable, NSError *_Nullable))completion; -/// Asynchronously uploads a file to the currently specified StorageReference. -/// @param fileURL A URL representing the system file path of the object to be uploaded. -/// @param metadata StorageMetadata containing additional information (MIME type, etc.) +/// Asynchronously uploads a file to the currently specified StorageReference. +/// \param fileURL A URL representing the system file path of the object to be uploaded. +/// +/// \param metadata StorageMetadata containing additional information (MIME type, etc.) /// about the object being uploaded. -/// @return An instance of StorageUploadTask, which can be used to monitor or manage the upload. +/// +/// +/// returns: +/// An instance of StorageUploadTask, which can be used to monitor or manage the +/// upload. - (FIRStorageUploadTask *_Nonnull)putFile:(NSURL *_Nonnull)fileURL metadata:(FIRStorageMetadata *_Nullable)metadata; -/// Asynchronously uploads a file to the currently specified StorageReference, +/// Asynchronously uploads a file to the currently specified StorageReference, /// without additional metadata. /// @param fileURL A URL representing the system file path of the object to be uploaded. /// @return An instance of StorageUploadTask, which can be used to monitor or manage the upload. - (FIRStorageUploadTask *_Nonnull)putFile:(NSURL *_Nonnull)fileURL; -/// Asynchronously uploads a file to the currently specified StorageReference. -/// @param fileURL A URL representing the system file path of the object to be uploaded. -/// @param metadata StorageMetadata containing additional information (MIME type, etc.) +/// Asynchronously uploads a file to the currently specified StorageReference. +/// \param fileURL A URL representing the system file path of the object to be uploaded. +/// +/// \param metadata StorageMetadata containing additional information (MIME type, etc.) /// about the object being uploaded. -/// @param completion A completion block that either returns the object metadata on success, +/// +/// \param completion A completion block that either returns the object metadata on success, /// or an error on failure. -/// @return An instance of StorageUploadTask, which can be used to monitor or manage the upload. +/// +/// +/// returns: +/// An instance of StorageUploadTask, which can be used to monitor or manage the +/// upload. - (FIRStorageUploadTask *_Nonnull)putFile:(NSURL *_Nonnull)fileURL metadata:(FIRStorageMetadata *_Nullable)metadata completion:(void (^_Nullable)(FIRStorageMetadata *_Nullable, NSError *_Nullable))completion; -/// Asynchronously downloads the object at the StorageReference to an Data object in memory. -/// An Data of the provided max size will be allocated, so ensure that the device has enough free -/// memory to complete the download. For downloading large files, writeToFile may be a better -/// option. -/// @param maxSize The maximum size in bytes to download. If the download exceeds this size, -/// the task will be cancelled and an error will be returned. -/// @param completion A completion block that either returns the object data on success, +/// Asynchronously downloads the object at the StorageReference to a Data +/// instance in memory. A Data buffer of the provided max size will be allocated, so +/// ensure that the device has enough free memory to complete the download. For downloading large +/// files, write(toFile:) may be a better option. \param maxSize The maximum size in +/// bytes to download. If the download exceeds this size, the task will be cancelled and an error +/// will be returned. +/// +/// \param completion A completion block that either returns the object data on success, /// or an error on failure. -/// @return An StorageDownloadTask that can be used to monitor or manage the download. +/// +/// +/// returns: +/// An StorageDownloadTask that can be used to monitor or manage the download. - (FIRStorageDownloadTask *_Nonnull) dataWithMaxSize:(int64_t)maxSize completion:(void (^_Nonnull)(NSData *_Nullable, NSError *_Nullable))completion; /// Asynchronously retrieves a long lived download URL with a revokable token. /// This can be used to share the file with others, but can be revoked by a developer /// in the Firebase Console. -/// @param completion A completion block that either returns the URL on success, +/// \param completion A completion block that either returns the URL on success, /// or an error on failure. +/// - (void)downloadURLWithCompletion:(void (^_Nonnull)(NSURL *_Nullable, NSError *_Nullable))completion; /// Asynchronously downloads the object at the current path to a specified system filepath. -/// @param fileURL A file system URL representing the path the object should be downloaded to. -/// @return An StorageDownloadTask that can be used to monitor or manage the download. +///
    +///
  • +/// Returns An StorageDownloadTask that can be used to monitor or manage the +/// download. +///
  • +///
+/// \param fileURL A file system URL representing the path the object should be downloaded to. +/// - (FIRStorageDownloadTask *_Nonnull)writeToFile:(NSURL *_Nonnull)fileURL; /// Asynchronously downloads the object at the current path to a specified system filepath. -/// @param fileURL A file system URL representing the path the object should be downloaded to. -/// @param completion A completion block that fires when the file download completes. -/// Returns an URL pointing to the file path of the downloaded file on success, +/// \param fileURL A file system URL representing the path the object should be downloaded to. +/// +/// \param completion A closure that fires when the file download completes, passed either +/// a URL pointing to the file path of the downloaded file on success, /// or an error on failure. -/// @return An StorageDownloadTask that can be used to monitor or manage the download. +/// +/// +/// returns: +/// A StorageDownloadTask that can be used to monitor or manage the download. - (FIRStorageDownloadTask *_Nonnull)writeToFile:(NSURL *_Nonnull)fileURL completion:(void (^_Nullable)(NSURL *_Nullable, NSError *_Nullable))completion; -/// List all items (files) and prefixes (folders) under this StorageReference. -/// This is a helper method for calling list() repeatedly until there are no more results. -/// Consistency of the result is not guaranteed if objects are inserted or removed while this -/// operation is executing. All results are buffered in memory. +/// Lists all items (files) and prefixes (folders) under this StorageReference. +/// This is a helper method for calling list() repeatedly until there are no more +/// results. Consistency of the result is not guaranteed if objects are inserted or removed while +/// this operation is executing. All results are buffered in memory. /// listAll(completion:) is only available for projects using Firebase Rules Version 2. -/// @param completion A completion handler that will be invoked with all items and prefixes under -/// the current StorageReference. +/// \param completion A completion handler that will be invoked with all items and prefixes under +/// the current StorageReference. +/// - (void)listAllWithCompletion:(void (^_Nonnull)(FIRStorageListResult *_Nullable, NSError *_Nullable))completion; /// List up to maxResults items (files) and prefixes (folders) under this /// StorageReference. “/” is treated as a path delimiter. Firebase Storage does not support /// unsupported object paths that end with “/” or contain two consecutive “/“s. All invalid objects /// in GCS will be filtered. list(maxResults:completion:) is only available for -/// projects using Firebase Rules Version 2. -/// @param maxResults The maximum number of results to return in a single page. Must be greater -/// than 0 and at most 1000. -/// @param completion A completion handler that will be invoked with up to maxResults items and -/// prefixes under the current StorageReference. +/// projects using Firebase Rules Version 2. \param maxResults The maximum number of results to +/// return in a single page. Must be greater than 0 and at most 1000. +/// +/// \param completion A completion handler that will be invoked with up to maxResults +/// items and prefixes under the current StorageReference. +/// - (void)listWithMaxResults:(int64_t)maxResults completion:(void (^_Nonnull)(FIRStorageListResult *_Nullable, NSError *_Nullable))completion; -/// Resumes a previous call to list(maxResults:completion:)`, starting after a pagination token. -/// Returns the next set of items (files) and prefixes (folders) under this StorageReference. -/// “/” is treated as a path delimiter. Firebase Storage does not support unsupported object -/// paths that end with “/” or contain two consecutive “/“s. All invalid objects in GCS will be -/// filtered. -/// list(maxResults:pageToken:completion:)is only available for projects using Firebase -/// Rules Version 2. -/// @param maxResults The maximum number of results to return in a single page. Must be greater -/// than 0 and at most 1000. -/// @param pageToken A page token from a previous call to list. -/// @param completion A completion handler that will be invoked with the next items and prefixes +/// Resumes a previous call to list(maxResults:completion:), starting after a +/// pagination token. Returns the next set of items (files) and prefixes (folders) under this +/// StorageReference. “/” is treated as a path delimiter. Storage does not support +/// unsupported object paths that end with “/” or contain two consecutive “/“s. All invalid objects +/// in GCS will be filtered. list(maxResults:pageToken:completion:)is only available +/// for projects using Firebase Rules Version 2. \param maxResults The maximum number of results to +/// return in a single page. Must be greater than 0 and at most 1000. +/// +/// \param pageToken A page token from a previous call to list. +/// +/// \param completion A completion handler that will be invoked with the next items and prefixes /// under the current StorageReference. +/// - (void)listWithMaxResults:(int64_t)maxResults pageToken:(NSString *_Nonnull)pageToken completion:(void (^_Nonnull)(FIRStorageListResult *_Nullable, NSError *_Nullable))completion; /// Retrieves metadata associated with an object at the current path. -/// @param completion A completion block which returns the object metadata on success, +/// \param completion A completion block which returns the object metadata on success, /// or an error on failure. +/// - (void)metadataWithCompletion:(void (^_Nonnull)(FIRStorageMetadata *_Nullable, NSError *_Nullable))completion; /// Updates the metadata associated with an object at the current path. -/// @param metadata An StorageMetadata object with the metadata to update. -/// @param completion A completion block which returns the StorageMetadata on success, +/// \param metadata A StorageMetadata object with the metadata to update. +/// +/// \param completion A completion block which returns the StorageMetadata on success, /// or an error on failure. +/// - (void)updateMetadata:(FIRStorageMetadata *_Nonnull)metadata completion: (void (^_Nullable)(FIRStorageMetadata *_Nullable, NSError *_Nullable))completion; /// Deletes the object at the current path. -/// @param completion A completion block which returns nil on success, or an error on failure. +/// \param completion A completion block which returns a nonnull error on failure. +/// - (void)deleteWithCompletion:(void (^_Nullable)(NSError *_Nullable))completion; - (FIRStorageReference *_Nonnull)copy:(struct _NSZone *_Nonnull)zone SWIFT_WARN_UNUSED_RESULT; - (BOOL)isEqual:(id _Nullable)object SWIFT_WARN_UNUSED_RESULT; @@ -659,22 +757,22 @@ SWIFT_CLASS_NAMED("StorageReference") @class NSProgress; -/// StorageTaskSnapshot represents an immutable view of a task. -/// A Snapshot contains a task, storage reference, metadata (if it exists), +/// StorageTaskSnapshot represents an immutable view of a task. +/// A snapshot contains a task, storage reference, metadata (if it exists), /// progress, and an error (if one occurred). SWIFT_CLASS_NAMED("StorageTaskSnapshot") @interface FIRStorageTaskSnapshot : NSObject -/// Subclass of StorageTask this snapshot represents. +/// The task this snapshot represents. @property(nonatomic, readonly, strong) FIRStorageTask *_Nonnull task; -/// Metadata returned by the task, or nil if no metadata returned. +/// Metadata returned by the task, or nil if no metadata returned. @property(nonatomic, readonly, strong) FIRStorageMetadata *_Nullable metadata; -/// StorageReference this task is operates on. +/// The StorageReference this task operates on. @property(nonatomic, readonly, strong) FIRStorageReference *_Nonnull reference; -/// Progress object which tracks the progress of an upload or download. +/// An object which tracks the progress of an upload or download. @property(nonatomic, readonly, strong) NSProgress *_Nullable progress; -/// Error during task execution, or nil if no error occurred. +/// An error raised during task execution, or nil if no error occurred. @property(nonatomic, readonly) NSError *_Nullable error; -/// Status of the task. +/// The status of the task. @property(nonatomic, readonly) enum FIRStorageTaskStatus status; @property(nonatomic, readonly, copy) NSString *_Nonnull description; - (nonnull instancetype)init SWIFT_UNAVAILABLE; @@ -687,13 +785,13 @@ typedef SWIFT_ENUM_NAMED(NSInteger, FIRStorageTaskStatus, "StorageTaskStatus", o FIRStorageTaskStatusSuccess = 4, FIRStorageTaskStatusFailure = 5, }; -/// StorageUploadTask implements resumable uploads to a file in Firebase Storage. +/// StorageUploadTask implements resumable uploads to a file in Firebase Storage. /// Uploads can be returned on completion with a completion callback, and can be monitored -/// by attaching observers, or controlled by calling StorageTask#pause, StorageTask#resume, -/// or StorageTask#cancel. -/// Uploads can takeData in memory, or an URL to a file on disk. +/// by attaching observers, or controlled by calling pause(), resume(), +/// or cancel(). +/// Uploads can be initialized from Data in memory, or a URL to a file on disk. /// Uploads are performed on a background queue, and callbacks are raised on the developer -/// specified callbackQueue in Storage, or the main queue if left unspecified. +/// specified callbackQueue in Storage, or the main queue if unspecified. /// Currently all uploads must be initiated and managed on the main queue. SWIFT_CLASS_NAMED("StorageUploadTask") @interface FIRStorageUploadTask : FIRStorageObservableTask @@ -701,9 +799,9 @@ SWIFT_CLASS_NAMED("StorageUploadTask") - (void)enqueue; /// Pauses a task currently in progress. - (void)pause; -/// Pauses a task currently in progress. +/// Cancels a task. - (void)cancel; -/// Pauses a task currently in progress. +/// Resumes a paused task. - (void)resume; @end diff --git a/ios_pod/swift_headers/SwiftProtobuf-Swift.h b/ios_pod/swift_headers/SwiftProtobuf-Swift.h index 8f203aef65..0e02a6606f 100644 --- a/ios_pod/swift_headers/SwiftProtobuf-Swift.h +++ b/ios_pod/swift_headers/SwiftProtobuf-Swift.h @@ -1,5 +1,5 @@ // Copyright 2022 Google LLC -// Copied from Firebase iOS SDK 9.0.0. +// Copied from Firebase iOS SDK 9.1.0. // Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 // clang-1316.0.20.8) diff --git a/messaging/integration_test/Podfile b/messaging/integration_test/Podfile index 133c62a723..8443485695 100644 --- a/messaging/integration_test/Podfile +++ b/messaging/integration_test/Podfile @@ -4,12 +4,12 @@ use_frameworks! :linkage => :static target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Messaging', '9.0.0' + pod 'Firebase/Messaging', '9.1.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Messaging', '9.0.0' + pod 'Firebase/Messaging', '9.1.0' end post_install do |installer| diff --git a/release_build_files/readme.md b/release_build_files/readme.md index 190f7a0d73..d389878100 100644 --- a/release_build_files/readme.md +++ b/release_build_files/readme.md @@ -203,46 +203,46 @@ Feature | Required Frameworks and Cocoapods -------------------------- | --------------------------------------- Firebase AdMob | firebase_admob.xcframework | | firebase.xcframework -| | Firebase/Analytics Cocoapod (9.0.0) +| | Firebase/Analytics Cocoapod (9.1.0) | | Google-Mobile-Ads-SDK Cocoapod (7.69.0-cppsdk2) Firebase Analytics | firebase_analytics.xcframework | | firebase.xcframework -| | Firebase/Analytics Cocoapod (9.0.0) +| | Firebase/Analytics Cocoapod (9.1.0) Firebase Authentication | firebase_auth.xcframework | | firebase.xcframework -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Auth Cocoapod (9.1.0) Firebase Dynamic Links | firebase_dynamic_links.xcframework | | firebase.xcframework -| | Firebase/DynamicLinks Cocoapod (9.0.0) +| | Firebase/DynamicLinks Cocoapod (9.1.0) Cloud Firestore | firebase_firestore.xcframework | | firebase_auth.xcframework | | firebase.xcframework -| | Firebase/Firestore Cocoapod (9.0.0) -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Firestore Cocoapod (9.1.0) +| | Firebase/Auth Cocoapod (9.1.0) Firebase Functions | firebase_functions.xcframework | | firebase_auth.xcframework (optional) | | firebase.xcframework -| | Firebase/Functions Cocoapod (9.0.0) -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Functions Cocoapod (9.1.0) +| | Firebase/Auth Cocoapod (9.1.0) Firebase Installations | firebase_installations.xcframework | | firebase.xcframework -| | FirebaseInstallations Cocoapod (9.0.0) +| | FirebaseInstallations Cocoapod (9.1.0) Firebase Cloud Messaging | firebase_messaging.xcframework | | firebase.xcframework -| | Firebase/Messaging Cocoapod (9.0.0) +| | Firebase/Messaging Cocoapod (9.1.0) Firebase Realtime Database | firebase_database.xcframework | | firebase_auth.xcframework | | firebase.xcframework -| | Firebase/Database Cocoapod (9.0.0) -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Database Cocoapod (9.1.0) +| | Firebase/Auth Cocoapod (9.1.0) Firebase Remote Config | firebase_remote_config.xcframework | | firebase.xcframework -| | Firebase/RemoteConfig Cocoapod (9.0.0) +| | Firebase/RemoteConfig Cocoapod (9.1.0) Firebase Storage | firebase_storage.xcframework | | firebase_auth.xcframework | | firebase.xcframework -| | Firebase/Storage Cocoapod (9.0.0) -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Storage Cocoapod (9.1.0) +| | Firebase/Auth Cocoapod (9.1.0) Important: Each version of the Firebase C++ SDK supports a specific version of the Firebase iOS SDK. Please ensure that you reference the Cocoapod versions @@ -267,46 +267,46 @@ Feature | Required Libraries and Cocoapods -------------------------- | ----------------------------------------- Firebase AdMob | libfirebase_admob.a | | libfirebase_app.a -| | Firebase/Analytics Cocoapod (9.0.0) +| | Firebase/Analytics Cocoapod (9.1.0) | | Google-Mobile-Ads-SDK Cocoapod (7.69.0-cppsdk2) Firebase Analytics | libfirebase_analytics.a | | libfirebase_app.a -| | Firebase/Analytics Cocoapod (9.0.0) +| | Firebase/Analytics Cocoapod (9.1.0) Firebase Authentication | libfirebase_auth.a | | libfirebase_app.a -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Auth Cocoapod (9.1.0) Firebase Dynamic Links | libfirebase_dynamic_links.a | | libfirebase_app.a -| | Firebase/DynamicLinks Cocoapod (9.0.0) +| | Firebase/DynamicLinks Cocoapod (9.1.0) Cloud Firestore | libfirebase_firestore.a | | libfirebase_app.a | | libfirebase_auth.a -| | Firebase/Firestore Cocoapod (9.0.0) -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Firestore Cocoapod (9.1.0) +| | Firebase/Auth Cocoapod (9.1.0) Firebase Functions | libfirebase_functions.a | | libfirebase_app.a | | libfirebase_auth.a (optional) -| | Firebase/Functions Cocoapod (9.0.0) -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Functions Cocoapod (9.1.0) +| | Firebase/Auth Cocoapod (9.1.0) Firebase Installations | libfirebase_installations.a | | libfirebase_app.a -| | FirebaseInstallations Cocoapod (9.0.0) +| | FirebaseInstallations Cocoapod (9.1.0) Firebase Cloud Messaging | libfirebase_messaging.a | | libfirebase_app.a -| | Firebase/CloudMessaging Cocoapod (9.0.0) +| | Firebase/CloudMessaging Cocoapod (9.1.0) Firebase Realtime Database | libfirebase_database.a | | libfirebase_app.a | | libfirebase_auth.a -| | Firebase/Database Cocoapod (9.0.0) -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Database Cocoapod (9.1.0) +| | Firebase/Auth Cocoapod (9.1.0) Firebase Remote Config | libfirebase_remote_config.a | | libfirebase_app.a -| | Firebase/RemoteConfig Cocoapod (9.0.0) +| | Firebase/RemoteConfig Cocoapod (9.1.0) Firebase Storage | libfirebase_storage.a | | libfirebase_app.a | | libfirebase_auth.a -| | Firebase/Storage Cocoapod (9.0.0) -| | Firebase/Auth Cocoapod (9.0.0) +| | Firebase/Storage Cocoapod (9.1.0) +| | Firebase/Auth Cocoapod (9.1.0) Important: Each version of the Firebase C++ SDK supports a specific version of the Firebase iOS SDK. Please ensure that you reference the Cocoapod versions diff --git a/remote_config/integration_test/Podfile b/remote_config/integration_test/Podfile index cb23fca811..e0e1c1916d 100644 --- a/remote_config/integration_test/Podfile +++ b/remote_config/integration_test/Podfile @@ -4,12 +4,12 @@ use_frameworks! :linkage => :static target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/RemoteConfig', '9.0.0' + pod 'Firebase/RemoteConfig', '9.1.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/RemoteConfig', '9.0.0' + pod 'Firebase/RemoteConfig', '9.1.0' end post_install do |installer| diff --git a/storage/integration_test/Podfile b/storage/integration_test/Podfile index 15de55a65e..6a6a445c7c 100644 --- a/storage/integration_test/Podfile +++ b/storage/integration_test/Podfile @@ -4,14 +4,14 @@ use_frameworks! :linkage => :static target 'integration_test' do platform :ios, '10.0' - pod 'Firebase/Storage', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Storage', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end target 'integration_test_tvos' do platform :tvos, '12.0' - pod 'Firebase/Storage', '9.0.0' - pod 'Firebase/Auth', '9.0.0' + pod 'Firebase/Storage', '9.1.0' + pod 'Firebase/Auth', '9.1.0' end post_install do |installer| From 94b5f05e2fc3f1c77163d77261c8b977a0d1a2b3 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Tue, 31 May 2022 15:44:27 -0400 Subject: [PATCH 41/47] CMakeLists.txt: set(RE2_BUILD_TESTING OFF CACHE BOOL "") This fixes the following build error: ``` The following tests FAILED: 1 - charclass_test (Not Run) 2 - compile_test (Not Run) 3 - filtered_re2_test (Not Run) 4 - mimics_pcre_test (Not Run) ... ``` e.g. https://github.com/firebase/firebase-cpp-sdk/runs/6676610733 This is caused by the addition of re2 to the firebase-ios-sdk in https://github.com/firebase/firebase-ios-sdk/pull/9488. I'm not sure _why_ these tests can't be found; but they're superfluous anyways. So just disable them. --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb610fdc90..83b2a3fde5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,6 +214,9 @@ endif() # firebase-ios-sdk since it's not needed and can sometimes fail to build. set(FIRESTORE_INCLUDE_OBJC OFF CACHE BOOL "Disabled for the CPP SDK") +# Disable re2 build tests +set(RE2_BUILD_TESTING OFF CACHE BOOL "") + if(FIREBASE_CPP_USE_PRIOR_GRADLE_BUILD) # Quote meta characters in ${CMAKE_CURRENT_LIST_DIR} so we can # match it in a regex. From 2589c43f757b7684067c1a150abd11dcfc5b2c5a Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Tue, 31 May 2022 16:01:36 -0400 Subject: [PATCH 42/47] firestore.cmake: bump pinned commit --- cmake/external/firestore.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index 43e34f2e89..eba8656f9d 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -37,8 +37,8 @@ function(GetReleasedDep) DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} GIT_REPOSITORY "https://github.com/firebase/firebase-ios-sdk.git" - # Pinned HEAD commit as of May 27, 2022 @ 15:36 EDT. - GIT_TAG c2bc549a7017c456a20ee69ca7ec27ea4a6077bd + # Pinned HEAD commit as of May 31, 2022 @ 16:01 EDT. + GIT_TAG 1658c4051e742d88105a6b23ffb4f8fabb0c00f0 PREFIX ${PROJECT_BINARY_DIR} From 895126fc9ab804785f76d33ebfffc3cc83b1e58d Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 1 Jun 2022 14:19:45 +0000 Subject: [PATCH 43/47] value_util.cc: Fix MaxValue() to no longer use designated initialization. This ports https://github.com/firebase/firebase-ios-sdk/pull/9868 to the firebase-cpp-sdk repository by patching the firebase-ios-sdk when it is cloned. Once the dependency on the firebase-ios-sdk is updated to a version that already includes https://github.com/firebase/firebase-ios-sdk/pull/9868 then this commit should be reverted. --- cmake/external/firestore_snappy.patch.txt | 65 +++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/cmake/external/firestore_snappy.patch.txt b/cmake/external/firestore_snappy.patch.txt index 317ecc6823..f1742fb965 100644 --- a/cmake/external/firestore_snappy.patch.txt +++ b/cmake/external/firestore_snappy.patch.txt @@ -617,3 +617,68 @@ index 000000000..28bfb0837 + const uint8_t*& ip = *ip_p; + // This section is crucial for the throughput of the decompression loop. + // The latency of an iteration is fundamentally constrained by the +diff --git a/Firestore/core/src/model/value_util.cc b/Firestore/core/src/model/value_util.cc +index 1b6bf07e0..41d1d6d26 100644 +--- a/Firestore/core/src/model/value_util.cc ++++ b/Firestore/core/src/model/value_util.cc +@@ -53,26 +53,6 @@ const char* kRawMaxValueFieldValue = "__max__"; + pb_bytes_array_s* kMaxValueFieldValue = + nanopb::MakeBytesArray(kRawMaxValueFieldValue); + +-/** The special map field value entry of a maximum proto value. */ +-google_firestore_v1_MapValue_FieldsEntry kMaxValueFieldEntry = { +- .key = kMaxValueFieldKey, +- .value = { +- .which_value_type = google_firestore_v1_Value_string_value_tag, +- .string_value = const_cast(kMaxValueFieldValue)}}; +- +-/** The special map value of a maximum proto value. */ +-_google_firestore_v1_MapValue kMaxValueMapValue = { +- .fields_count = 1, .fields = &kMaxValueFieldEntry}; +- +-/** +- * A maximum value that is larger than any other Firestore values. Underlying it +- * is a map value with a special map field that SDK user cannot possibly +- * construct. +- */ +-google_firestore_v1_Value kMaxValue = { +- .which_value_type = google_firestore_v1_Value_map_value_tag, +- .map_value = kMaxValueMapValue}; +- + } // namespace + + using nanopb::Message; +@@ -703,8 +683,32 @@ bool IsMinValue(const google_firestore_v1_Value& value) { + return IsNullValue(value); + } + ++/** ++ * Creates and returns a maximum value that is larger than any other Firestore ++ * values. Underlying it is a map value with a special map field that SDK user ++ * cannot possibly construct. ++ */ + google_firestore_v1_Value MaxValue() { +- return kMaxValue; ++ google_firestore_v1_Value value; ++ value.which_value_type = google_firestore_v1_Value_string_value_tag; ++ value.string_value = kMaxValueFieldValue; ++ ++ // Make `field_entry` static so that it has a memory address that outlives ++ // this function's scope; otherwise, using its address in the `map_value` ++ // variable below would be invalid by the time the caller accessed it. ++ static google_firestore_v1_MapValue_FieldsEntry field_entry; ++ field_entry.key = kMaxValueFieldKey; ++ field_entry.value = value; ++ ++ google_firestore_v1_MapValue map_value; ++ map_value.fields_count = 1; ++ map_value.fields = &field_entry; ++ ++ google_firestore_v1_Value max_value; ++ max_value.which_value_type = google_firestore_v1_Value_map_value_tag; ++ max_value.map_value = map_value; ++ ++ return max_value; + } + + bool IsMaxValue(const google_firestore_v1_Value& value) { From 388803782574289df178c30ffd4b2e5dae81af12 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Tue, 31 May 2022 16:01:36 -0400 Subject: [PATCH 44/47] firestore.cmake: bump pinned commit --- cmake/external/firestore.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/external/firestore.cmake b/cmake/external/firestore.cmake index eba8656f9d..58fd8ac5c2 100644 --- a/cmake/external/firestore.cmake +++ b/cmake/external/firestore.cmake @@ -37,8 +37,8 @@ function(GetReleasedDep) DOWNLOAD_DIR ${FIREBASE_DOWNLOAD_DIR} GIT_REPOSITORY "https://github.com/firebase/firebase-ios-sdk.git" - # Pinned HEAD commit as of May 31, 2022 @ 16:01 EDT. - GIT_TAG 1658c4051e742d88105a6b23ffb4f8fabb0c00f0 + # Pinned HEAD commit as of June 01, 2022 @ 10:51 EDT. + GIT_TAG 89c38d1ed908dbc10d5f9f7aded4cf271113773f PREFIX ${PROJECT_BINARY_DIR} From dcd6fe98ccc125fb57d8810a21f7722afd1870ca Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 24 Jun 2022 00:59:35 -0400 Subject: [PATCH 45/47] project.pbxproj: add transaction_options_test.cc --- .../integration_test.xcodeproj/project.pbxproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/firestore/integration_test_internal/integration_test.xcodeproj/project.pbxproj b/firestore/integration_test_internal/integration_test.xcodeproj/project.pbxproj index 75c12490f8..a2b4b16315 100644 --- a/firestore/integration_test_internal/integration_test.xcodeproj/project.pbxproj +++ b/firestore/integration_test_internal/integration_test.xcodeproj/project.pbxproj @@ -94,6 +94,8 @@ D6ED33BD2606CD890058CBF9 /* future_test_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6ED33B92606CD890058CBF9 /* future_test_util.cc */; }; D6ED33BE2606CD890058CBF9 /* integration_test_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = D6ED33BB2606CD890058CBF9 /* integration_test_util.cc */; }; D86FB1D3D4A592C451A29369 /* firebase_firestore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B7F45B5446094E107E88721A /* firebase_firestore.framework */; }; + ED39362728657B740050FE2B /* transaction_options_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED39362628657B740050FE2B /* transaction_options_test.cc */; }; + ED39362828657B740050FE2B /* transaction_options_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED39362628657B740050FE2B /* transaction_options_test.cc */; }; EDEEC7632800CD0000EFBAAF /* leveldb_snappy_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EDEEC7622800CD0000EFBAAF /* leveldb_snappy_test.cc */; }; EDEEC7642800CD0000EFBAAF /* leveldb_snappy_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EDEEC7622800CD0000EFBAAF /* leveldb_snappy_test.cc */; }; /* End PBXBuildFile section */ @@ -171,6 +173,7 @@ D6ED33BB2606CD890058CBF9 /* integration_test_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = integration_test_util.cc; path = src/util/integration_test_util.cc; sourceTree = ""; }; D6ED33BC2606CD890058CBF9 /* future_test_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = future_test_util.h; path = src/util/future_test_util.h; sourceTree = ""; }; EAFAF9474EC412ADCC65F2CC /* firebase_firestore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = firebase_firestore.framework; path = Frameworks/firebase_firestore.framework; sourceTree = ""; }; + ED39362628657B740050FE2B /* transaction_options_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = transaction_options_test.cc; path = src/transaction_options_test.cc; sourceTree = ""; }; EDEEC7622800CD0000EFBAAF /* leveldb_snappy_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = leveldb_snappy_test.cc; path = src/leveldb_snappy_test.cc; sourceTree = ""; }; /* End PBXFileReference section */ @@ -262,6 +265,7 @@ 5292271D1C85FB5500C89379 /* src */ = { isa = PBXGroup; children = ( + ED39362628657B740050FE2B /* transaction_options_test.cc */, D60C58862819C902002E8A04 /* empty.swift */, EDEEC7622800CD0000EFBAAF /* leveldb_snappy_test.cc */, 12D513182684C8D100A83FAA /* bundle_builder.cc */, @@ -567,6 +571,7 @@ D6ED33BD2606CD890058CBF9 /* future_test_util.cc in Sources */, D6AAAD592606C22D0025C53B /* firestore_integration_test.cc in Sources */, D6C179EE22CB323300C2651A /* firebase_test_framework.cc in Sources */, + ED39362728657B740050FE2B /* transaction_options_test.cc in Sources */, D6AAAD4B2606C22D0025C53B /* array_transform_test.cc in Sources */, D6AAAD512606C22D0025C53B /* sanity_test.cc in Sources */, D6AAAD482606C22D0025C53B /* cursor_test.cc in Sources */, @@ -590,6 +595,7 @@ BC1D6843267B00EB005DC2DA /* numeric_transforms_test.cc in Sources */, BC1D6844267B00EB005DC2DA /* array_transform_test.cc in Sources */, BC1D6854267B00EB005DC2DA /* listener_registration_test.cc in Sources */, + ED39362828657B740050FE2B /* transaction_options_test.cc in Sources */, BC1D683F267B00EB005DC2DA /* document_snapshot_test.cc in Sources */, BC1D684E267B00EB005DC2DA /* includes_test.cc in Sources */, BC1D684C267B00EB005DC2DA /* document_change_test.cc in Sources */, From 238fd003d93402e1c433a020a68a12d2a6204730 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 24 Jun 2022 02:28:04 -0400 Subject: [PATCH 46/47] transaction_options.cc: add missing #include --- firestore/src/common/transaction_options.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/firestore/src/common/transaction_options.cc b/firestore/src/common/transaction_options.cc index 1e48673f55..87e6d7309e 100644 --- a/firestore/src/common/transaction_options.cc +++ b/firestore/src/common/transaction_options.cc @@ -17,6 +17,7 @@ #include "firestore/src/include/firebase/firestore/transaction_options.h" #include +#include #include #include "firestore/src/common/exception_common.h" From d1b28aa59ad2be504c0e5073931518f0949ffc1d Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 24 Jun 2022 02:28:56 -0400 Subject: [PATCH 47/47] app/CMakeLists.txt: add transaction_options.h to firestore_HDRS --- app/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 2c6561ffd6..801a924e9a 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -494,6 +494,7 @@ if (IOS) ${FIREBASE_SOURCE_DIR}/firestore/src/include/firebase/firestore/snapshot_metadata.h ${FIREBASE_SOURCE_DIR}/firestore/src/include/firebase/firestore/source.h ${FIREBASE_SOURCE_DIR}/firestore/src/include/firebase/firestore/transaction.h + ${FIREBASE_SOURCE_DIR}/firestore/src/include/firebase/firestore/transaction_options.h ${FIREBASE_SOURCE_DIR}/firestore/src/include/firebase/firestore/write_batch.h ${FIREBASE_POD_DIR}/Pods/FirebaseFirestore/Firestore/core/include/firebase/firestore/firestore_errors.h ${FIREBASE_POD_DIR}/Pods/FirebaseFirestore/Firestore/core/include/firebase/firestore/firestore_version.h