diff --git a/src/ios/RealmJS.xcodeproj/project.pbxproj b/src/ios/RealmJS.xcodeproj/project.pbxproj index ae4ddfb0..f5a454da 100644 --- a/src/ios/RealmJS.xcodeproj/project.pbxproj +++ b/src/ios/RealmJS.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 02409DC21BCF11D6005F3B3E /* RealmJSCoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 02409DC11BCF11D6005F3B3E /* RealmJSCoreTests.m */; }; 0270BC821B7D020100010E03 /* RealmJSTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC7B1B7D020100010E03 /* RealmJSTests.mm */; }; 027A23131CD3E379000543AE /* libRealmJS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F63FF2B11C1241E500B3B8E0 /* libRealmJS.a */; }; + 02D041F71CE11159000E4250 /* dates-v3.realm in Resources */ = {isa = PBXBuildFile; fileRef = 02D041F61CE11159000E4250 /* dates-v3.realm */; }; 02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; }; 02F59EBF1C88F17D007F774C /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EAF1C88F17D007F774C /* index_set.cpp */; }; 02F59EC01C88F17D007F774C /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F59EB11C88F17D007F774C /* list.cpp */; }; @@ -102,6 +103,7 @@ 02A3C7A41BC4341500B1A7BE /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; 02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmJSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + 02D041F61CE11159000E4250 /* dates-v3.realm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "dates-v3.realm"; sourceTree = ""; }; 02F59EAE1C88F17D007F774C /* binding_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = binding_context.hpp; path = src/binding_context.hpp; sourceTree = ""; }; 02F59EAF1C88F17D007F774C /* index_set.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = index_set.cpp; path = src/index_set.cpp; sourceTree = ""; }; 02F59EB01C88F17D007F774C /* index_set.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = index_set.hpp; path = src/index_set.hpp; sourceTree = ""; }; @@ -295,6 +297,7 @@ isa = PBXGroup; children = ( F61378781C18EAAC008BFC51 /* js */, + 02D041F51CE11159000E4250 /* data */, 0270BC781B7D020100010E03 /* Info.plist */, 0270BC7A1B7D020100010E03 /* RealmJSTests.h */, 0270BC7B1B7D020100010E03 /* RealmJSTests.mm */, @@ -321,6 +324,14 @@ name = Frameworks; sourceTree = ""; }; + 02D041F51CE11159000E4250 /* data */ = { + isa = PBXGroup; + children = ( + 02D041F61CE11159000E4250 /* dates-v3.realm */, + ); + path = data; + sourceTree = ""; + }; F62A35131C18E6E2004A917D /* iOS */ = { isa = PBXGroup; children = ( @@ -619,6 +630,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 02D041F71CE11159000E4250 /* dates-v3.realm in Resources */, F6BCCFE21C8380A400FE31AE /* lib in Resources */, F61378791C18EAC5008BFC51 /* js in Resources */, ); diff --git a/src/ios/platform.mm b/src/ios/platform.mm index 00013d5e..fbfe2f57 100644 --- a/src/ios/platform.mm +++ b/src/ios/platform.mm @@ -64,6 +64,25 @@ void ensure_directory_exists_for_file(const std::string &fileName) } } +void copy_bundled_realm_files() +{ + for (id bundle in [NSBundle allBundles]) { + NSString *resourcePath = [bundle resourcePath]; + NSString *docsDir = @(default_realm_file_directory().c_str()); + NSFileManager *manager = [NSFileManager defaultManager]; + + for (NSString *path in [manager enumeratorAtPath:resourcePath]) { + if (![path containsString:@".realm"]) { + continue; + } + NSError *error; + if (![manager copyItemAtPath:[resourcePath stringByAppendingPathComponent:path] toPath:[docsDir stringByAppendingPathComponent:path] error:&error]) { + throw std::runtime_error((std::string)"Failed to copy file at path " + path.UTF8String); + } + } + } +} + void remove_realm_files_from_directory(const std::string &directory) { NSFileManager *manager = [NSFileManager defaultManager]; diff --git a/src/js_realm.hpp b/src/js_realm.hpp index ee4d675f..04935ed8 100644 --- a/src/js_realm.hpp +++ b/src/js_realm.hpp @@ -154,7 +154,8 @@ class Realm { static void constructor(ContextType, ObjectType, size_t, const ValueType[]); static void schema_version(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); static void clear_test_state(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); - + static void copy_bundled_realm_files(ContextType, ObjectType, size_t, const ValueType[], ReturnValue &); + // static properties static void get_default_path(ContextType, ObjectType, ReturnValue &); static void set_default_path(ContextType, ObjectType, ValueType value); @@ -203,6 +204,7 @@ struct RealmClass : ClassDefinition { MethodMap const static_methods = { {"schemaVersion", wrap}, {"clearTestState", wrap}, + {"copyBundledRealmFiles", wrap}, }; PropertyMap const static_properties = { @@ -341,7 +343,25 @@ void Realm::constructor(ContextType ctx, ObjectType this_object, size_t argc, // Fix for datetime -> timestamp conversion if (realm->config().upgrade_initial_version != realm->config().upgrade_final_version && realm->config().upgrade_initial_version < 5) { - assert(0); + // any versions earlier than file format 5 are stored as milliseconds and need to be converted to the new format + for (auto object_schema : *realm->config().schema) { + auto table = ObjectStore::table_for_object_type(realm->read_group(), object_schema.name); + for (auto property : object_schema.properties) { + if (property.type == PropertyTypeDate) { + if (!realm->is_in_transaction()) { + realm->begin_transaction(); + } + + for (size_t row_index = 0; row_index < table->size(); row_index++) { + auto milliseconds = table->get_timestamp(property.table_column, row_index).get_seconds(); + table->set_timestamp(property.table_column, row_index, Timestamp(milliseconds / 1000, (milliseconds % 1000) * 1000000)); + } + } + } + if (realm->is_in_transaction()) { + realm->commit_transaction(); + } + } } auto delegate = new RealmDelegate(realm, Context::get_global_context(ctx)); @@ -378,6 +398,12 @@ void Realm::clear_test_state(ContextType ctx, ObjectType this_object, size_t validate_argument_count(argc, 0); delete_all_realms(); } + +template +void Realm::copy_bundled_realm_files(ContextType ctx, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { + validate_argument_count(argc, 0); + realm::copy_bundled_realm_files(); +} template void Realm::get_default_path(ContextType ctx, ObjectType object, ReturnValue &return_value) { diff --git a/src/object-store/src/shared_realm.cpp b/src/object-store/src/shared_realm.cpp index bff52bce..ae73a9a8 100644 --- a/src/object-store/src/shared_realm.cpp +++ b/src/object-store/src/shared_realm.cpp @@ -43,15 +43,13 @@ Realm::Config::Config(const Config& c) , cache(c.cache) , disable_format_upgrade(c.disable_format_upgrade) , automatic_change_notifications(c.automatic_change_notifications) -, upgrade_final_version(0) -, upgrade_initial_version(0) { if (c.schema) { schema = std::make_unique(*c.schema); } } -Realm::Config::Config() : schema_version(ObjectStore::NotVersioned), upgrade_initial_version(0), upgrade_final_version(0) { } +Realm::Config::Config() : schema_version(ObjectStore::NotVersioned) { } Realm::Config::Config(Config&&) = default; Realm::Config::~Config() = default; diff --git a/src/object-store/src/shared_realm.hpp b/src/object-store/src/shared_realm.hpp index 20cb630c..75b67694 100644 --- a/src/object-store/src/shared_realm.hpp +++ b/src/object-store/src/shared_realm.hpp @@ -82,9 +82,9 @@ namespace realm { // everything can be done deterministically on one thread, and // speeds up tests that don't need notifications. bool automatic_change_notifications = true; - // File format versions populated when a file format updrade takes place + // File format versions populated when a file format upgrade takes place // during realm opening - int upgrade_initial_version, upgrade_final_version; + int upgrade_initial_version = 0, upgrade_final_version = 0; Config(); Config(Config&&); diff --git a/src/platform.hpp b/src/platform.hpp index 266c86e7..7f497a79 100644 --- a/src/platform.hpp +++ b/src/platform.hpp @@ -37,6 +37,9 @@ std::string default_realm_file_directory(); // create the directories for the given filename void ensure_directory_exists_for_file(const std::string &file); +// copy all realm files from resources directory to default realm dir +void copy_bundled_realm_files(); + // remove all realm files in the given directory void remove_realm_files_from_directory(const std::string &directory); diff --git a/tests/js/object-tests.js b/tests/js/object-tests.js index 13e08cd1..dc80180c 100644 --- a/tests/js/object-tests.js +++ b/tests/js/object-tests.js @@ -471,6 +471,8 @@ module.exports = BaseTest.extend({ }, testCurrentDate: function() { + Realm.copyBundledRealmFiles(); + var DateSchema = { name: 'Date', properties: { @@ -478,7 +480,7 @@ module.exports = BaseTest.extend({ } }; - var realm = new Realm({schema: [DateSchema]}); + var realm = new Realm({path: 'dates-v3.realm', schema: [DateSchema]}); var currentDate = new Date(); var object; realm.write(function() { diff --git a/tests/react-test-app/ios/ReactTests.xcodeproj/project.pbxproj b/tests/react-test-app/ios/ReactTests.xcodeproj/project.pbxproj index cee3cd13..0c1d4eeb 100644 --- a/tests/react-test-app/ios/ReactTests.xcodeproj/project.pbxproj +++ b/tests/react-test-app/ios/ReactTests.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; 022D592F1C0432F1001E25FE /* RealmJSTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 022D592E1C0432F1001E25FE /* RealmJSTests.mm */; }; + 02D041E91CE11131000E4250 /* dates-v3.realm in Resources */ = {isa = PBXBuildFile; fileRef = 02D041E81CE11131000E4250 /* dates-v3.realm */; }; 02DE87671C0CE46100A42BFC /* RealmReactTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 02DE87661C0CE46100A42BFC /* RealmReactTests.m */; }; 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; @@ -136,6 +137,7 @@ 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; 00E356EE1AD99517003FC87E /* RealmReactTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmReactTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 022D592E1C0432F1001E25FE /* RealmJSTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJSTests.mm; path = ../../ios/RealmJSTests.mm; sourceTree = ""; }; + 02D041E81CE11131000E4250 /* dates-v3.realm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "dates-v3.realm"; sourceTree = ""; }; 02DE87661C0CE46100A42BFC /* RealmReactTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmReactTests.m; path = ReactTests/RealmReactTests.m; sourceTree = ""; }; 02DE87711C0CE55100A42BFC /* RealmJSTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmJSTests.h; path = ../../ios/RealmJSTests.h; sourceTree = ""; }; 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; @@ -226,6 +228,15 @@ name = Products; sourceTree = ""; }; + 02D041E71CE11131000E4250 /* data */ = { + isa = PBXGroup; + children = ( + 02D041E81CE11131000E4250 /* dates-v3.realm */, + ); + name = data; + path = ../../data; + sourceTree = ""; + }; 139105B71AF99BAD00B5F7CC /* Products */ = { isa = PBXGroup; children = ( @@ -305,6 +316,7 @@ 02DE87711C0CE55100A42BFC /* RealmJSTests.h */, 022D592E1C0432F1001E25FE /* RealmJSTests.mm */, 02DE87661C0CE46100A42BFC /* RealmReactTests.m */, + 02D041E71CE11131000E4250 /* data */, 13B07FAE1A68108700A75B9A /* ReactTests */, 832341AE1AAA6A7D00B99B32 /* Libraries */, 83CBBA001A601CBA00E9B192 /* Products */, @@ -541,6 +553,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 02D041E91CE11131000E4250 /* dates-v3.realm in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, );