Bgerstle has submitted this change and it was merged.

Change subject: Migration "fixes" -  Bug: T96607 Sending migration failures to 
OTRS Adding build number to user agent string Adding logic to remove old 
backups after 30 days Refactor many methods to be instance methods to make the 
classes testable Add tests for removing 
......................................................................


Migration "fixes" -  Bug: T96607
Sending migration failures to OTRS
Adding build number to user agent string
Adding logic to remove old backups after 30 days
Refactor many methods to be instance methods to make the classes testable
Add tests for removing and moving the store - but they don't work in the test 
bundle :(

Change-Id: I2c9dccbfb04803dc4d80ee8dcae64b76f13a39e3
---
M OldDataSchema/Data/ArticleDataContextSingleton.h
M OldDataSchema/Data/ArticleDataContextSingleton.m
M Wikipedia/AppDelegate.m
M Wikipedia/Data/OldDataSchemaMigrator.h
M Wikipedia/Data/OldDataSchemaMigrator.m
M Wikipedia/Data/OldDataSchemaMigrator_Private.h
M Wikipedia/View Controllers/DataMigration/DataMigrationProgressViewController.h
M Wikipedia/View Controllers/DataMigration/DataMigrationProgressViewController.m
M Wikipedia/mw-utils/WikipediaAppUtils.m
M WikipediaUnitTests/OldDataSchemaMigratorTests.m
10 files changed, 287 insertions(+), 145 deletions(-)

Approvals:
  Bgerstle: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/OldDataSchema/Data/ArticleDataContextSingleton.h 
b/OldDataSchema/Data/ArticleDataContextSingleton.h
index d533b7e..fd5b76a 100644
--- a/OldDataSchema/Data/ArticleDataContextSingleton.h
+++ b/OldDataSchema/Data/ArticleDataContextSingleton.h
@@ -1,5 +1,3 @@
-//  Created by Monte Hurd on 11/27/13.
-//  Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; 
please copy and modify!
 
 #import <CoreData/CoreData.h>
 
@@ -7,10 +5,33 @@
 
 + (ArticleDataContextSingleton *)sharedInstance;
 
+/**
+ *  The path to the DB
+ *
+ *  @return The path
+ */
+- (NSString*)databasePath;
+
+/**
+ *  Created lazily
+ */
 @property (nonatomic, retain) NSManagedObjectContext *mainContext;
 
+/**
+ *  Create a new background context. You are responsible for its lifecycle
+ *  and propagating changes to the store.
+ *
+ *  @return A new background context
+ */
 - (NSManagedObjectContext*)backgroundContext;
 
+/**
+ *  Automatically propagates changes to the store.
+ *  Use this for background contexts to handle the save propagation for you.
+ *
+ *  @param context         The context to save
+ *  @param completionBlock a completion block fired after the save operation
+ */
 - (void)saveContextAndPropagateChangesToStore:(NSManagedObjectContext*)context 
completionBlock:(void(^)(NSError* error))completionBlock;
 
 @end
diff --git a/OldDataSchema/Data/ArticleDataContextSingleton.m 
b/OldDataSchema/Data/ArticleDataContextSingleton.m
index e6182dc..7dd54fe 100644
--- a/OldDataSchema/Data/ArticleDataContextSingleton.m
+++ b/OldDataSchema/Data/ArticleDataContextSingleton.m
@@ -1,12 +1,8 @@
-//  Created by Monte Hurd on 11/27/13.
-//  Copyright (c) 2013 Wikimedia Foundation. Provided under MIT-style license; 
please copy and modify!
 
 #import "ArticleDataContextSingleton.h"
 #import "NSManagedObjectModel+OldDataSchema.h"
 
-@interface ArticleDataContextSingleton (){
-    
-}
+@interface ArticleDataContextSingleton ()
 
 @property (nonatomic, retain) NSManagedObjectContext *masterContext;
 
@@ -25,55 +21,66 @@
     return sharedInstance;
 }
 
-- (id)init
-{
-    self = [super init];
-    if (self) {
 
-        [self setupMasterContext];
+- (NSString*)databasePath{
+    
+    NSString *articlesDBPath = [[self documentRootPath] 
stringByAppendingString:@"/articleData6.sqlite"];
+    return articlesDBPath;
+}
+
+- (NSManagedObjectContext*)masterContext{
+    
+    if(!_masterContext){
+        
+        NSPersistentStoreCoordinator *persistentStoreCoordinator =
+        [[NSPersistentStoreCoordinator alloc] 
initWithManagedObjectModel:[NSManagedObjectModel wmf_oldDataSchema]];
+        
+        NSURL *url = [NSURL fileURLWithPath:[self databasePath]];
+        
+        NSDictionary *options = @{
+                                  
NSMigratePersistentStoresAutomaticallyOption: @YES,
+                                  NSInferMappingModelAutomaticallyOption: @YES
+                                  };
+        NSError *error = nil;
+        NSPersistentStore *persistentStore = [persistentStoreCoordinator 
addPersistentStoreWithType:NSSQLiteStoreType
+                                                                               
       configuration:nil
+                                                                               
                 URL:url
+                                                                               
             options:options
+                                                                               
               error:&error];
+        if (!persistentStore) {
+            NSLog(@"Error creating persistent store coordinator: %@", 
error.localizedFailureReason);
+            return nil;
+        }
+        
+        _masterContext = [[NSManagedObjectContext alloc] 
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
+        _masterContext.persistentStoreCoordinator = persistentStoreCoordinator;
+
+    }
+    
+    return _masterContext;
+}
+
+- (NSManagedObjectContext*)mainContext{
+    
+    if(!_mainContext){
+        
+        if(!self.masterContext){
+            return nil;
+        }
         
         // Setup main context.
-        self.mainContext = [[NSManagedObjectContext alloc] 
initWithConcurrencyType:NSMainQueueConcurrencyType];
-        self.mainContext.parentContext = self.masterContext;
+        _mainContext = [[NSManagedObjectContext alloc] 
initWithConcurrencyType:NSMainQueueConcurrencyType];
+        _mainContext.parentContext = self.masterContext;
         
         // Ensure object changes saved to mainContext bubble up to 
masterContext.
         [[NSNotificationCenter defaultCenter] addObserver:self
                                                  
selector:@selector(propagateMainSavesToMaster)
                                                      
name:NSManagedObjectContextDidSaveNotification
-                                                   object:self.mainContext];
-    }
-    return self;
-}
+                                                   object:_mainContext];
 
--(void)setupMasterContext
-{
-    // Setup the masterContext and attach the persistant store to it.
-    self.masterContext = [[NSManagedObjectContext alloc] 
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
-    
-    NSPersistentStoreCoordinator *persistentStoreCoordinator =
-        [[NSPersistentStoreCoordinator alloc] 
initWithManagedObjectModel:[NSManagedObjectModel wmf_oldDataSchema]];
-    
-    NSString *articlesDBPath = [[self documentRootPath] 
stringByAppendingString:@"/articleData6.sqlite"];
-    NSLog(@"\n\n\nArticle data path: %@\n\n\n", articlesDBPath);
-    NSURL *url = [NSURL fileURLWithPath:articlesDBPath];
-    
-    NSDictionary *options = @{
-                              NSMigratePersistentStoresAutomaticallyOption: 
@YES,
-                              NSInferMappingModelAutomaticallyOption: @YES
-                              };
-    NSError *error = nil;
-    NSPersistentStore *persistentStore = [persistentStoreCoordinator 
addPersistentStoreWithType:NSSQLiteStoreType
-                                                                               
   configuration:nil
-                                                                               
             URL:url
-                                                                               
         options:options
-                                                                               
         error:&error];
-    if (persistentStore) {
-        NSLog(@"Created persistent store.");
-    } else {
-        NSLog(@"Error creating persistent store coordinator: %@", 
error.localizedFailureReason);
     }
     
-    self.masterContext.persistentStoreCoordinator = persistentStoreCoordinator;
+    return _mainContext;
 }
 
 - (NSManagedObjectContext*)backgroundContext{
diff --git a/Wikipedia/AppDelegate.m b/Wikipedia/AppDelegate.m
index 32c5e32..952e7b0 100644
--- a/Wikipedia/AppDelegate.m
+++ b/Wikipedia/AppDelegate.m
@@ -15,6 +15,9 @@
 @interface AppDelegate ()
 <DataMigrationProgressDelegate>
 @property (nonatomic, weak) UIAlertView* dataMigrationAlert;
+
+@property (nonatomic, strong) DataMigrationProgressViewController* 
migrationViewController;
+
 @end
 
 @implementation AppDelegate
@@ -48,6 +51,7 @@
 #endif
 
     if (![self presentDataMigrationViewControllerIfNeeded]) {
+        [self performMigrationCleanup];
         [self presentRootViewController:NO withSplash:YES];
     }
 
@@ -69,6 +73,7 @@
 }
 
 - (void)presentRootViewController:(BOOL)animated withSplash:(BOOL)withSplash {
+    self.migrationViewController = nil;
     RootViewController* mainInitialVC =
         [[UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil] 
instantiateInitialViewController];
     NSParameterAssert([mainInitialVC isKindOfClass:[RootViewController 
class]]);
@@ -137,8 +142,21 @@
 
 #pragma mark - Migration
 
+- (DataMigrationProgressViewController*)migrationViewController {
+    if (!_migrationViewController) {
+        _migrationViewController          = 
[[DataMigrationProgressViewController alloc] init];
+        _migrationViewController.delegate = self;
+    }
+
+    return _migrationViewController;
+}
+
+- (void)performMigrationCleanup {
+    [self.migrationViewController removeOldDataBackupIfNeeded];
+}
+
 - (BOOL)presentDataMigrationViewControllerIfNeeded {
-    if ([DataMigrationProgressViewController needsMigration]) {
+    if ([self.migrationViewController needsMigration]) {
         UIAlertView* dialog =
             [[UIAlertView alloc] 
initWithTitle:MWLocalizedString(@"migration-prompt-title", nil)
                                        
message:MWLocalizedString(@"migration-prompt-message", nil)
@@ -160,12 +178,10 @@
 - (void)alertView:(UIAlertView*)alertView 
didDismissWithButtonIndex:(NSInteger)buttonIndex {
     if (alertView == self.dataMigrationAlert) {
         if (buttonIndex == alertView.cancelButtonIndex) {
-            [DataMigrationProgressViewController removeOldData];
+            [self.migrationViewController moveOldDataToBackupLocation];
             [self presentRootViewController:YES withSplash:NO];
         } else {
-            DataMigrationProgressViewController* migrationVC = 
[[DataMigrationProgressViewController alloc] init];
-            migrationVC.delegate = self;
-            [self transitionToRootViewController:migrationVC animated:NO];
+            [self transitionToRootViewController:self.migrationViewController 
animated:NO];
         }
     }
 }
diff --git a/Wikipedia/Data/OldDataSchemaMigrator.h 
b/Wikipedia/Data/OldDataSchemaMigrator.h
index bf7c549..fccf08d 100644
--- a/Wikipedia/Data/OldDataSchemaMigrator.h
+++ b/Wikipedia/Data/OldDataSchemaMigrator.h
@@ -1,10 +1,3 @@
-//
-//  OldDataSchema.h
-//  OldDataSchema
-//
-//  Created by Brion on 12/22/14.
-//  Copyright (c) 2014 Wikimedia Foundation. All rights reserved.
-//
 
 #import <Foundation/Foundation.h>
 
@@ -42,14 +35,64 @@
 @property (weak) id<OldDataSchemaDelegate> delegate;
 @property (weak) id<OldDataSchemaMigratorProgressDelegate> progressDelegate;
 
-+ (BOOL)exists;
+- (instancetype)initWithDatabasePath:(NSString*)databasePath;
+
+@property (nonatomic, strong, readonly) NSString* databasePath;
+@property (nonatomic, strong, readonly) NSString* backupDatabasePath;
+
+/**
+ *  Does the database exist
+ *
+ *  @return Yes if the database exist at the database path, NO if not.
+ */
+- (BOOL)exists;
+
+/**
+ *  Does a backup exist
+ *
+ *  @return Yes if the database exist at the backup path, NO if not.
+ */
+- (BOOL)backupExists;
+
+/**
+ *  Moves old data to backup location
+ *
+ *  @return YES if succesful, otherwise NO
+ */
+- (BOOL)moveOldDataToBackupLocation;
+
+/**
+ *  Removes old data if it is older than the grace period for backups
+ *
+ *  @return YES is removed, otherwise NO
+ */
+
+- (BOOL)removeOldDataIfOlderThanMaximumGracePeriod;
+
+/**
+ *  Removes backups immediately
+ *
+ *  @return YES is successful, otherwise NO
+ */
+- (BOOL)removebackupDataImmediately;
+
+
+
+
+/**
+ *  Set the context to use for migration
+ */
+@property (nonatomic, strong) NSManagedObjectContext* context;
 
 /**
  *  This runs asynchronously.
+ *  NOTE: You must set the context before calling this method
+ *
  *  Use the progress delegate methods to get notifified when the migration 
completes.
  */
 - (void)migrateData;
 
-+ (void)removeOldData;
+
+
 
 @end
diff --git a/Wikipedia/Data/OldDataSchemaMigrator.m 
b/Wikipedia/Data/OldDataSchemaMigrator.m
index cb45974..616cb07 100644
--- a/Wikipedia/Data/OldDataSchemaMigrator.m
+++ b/Wikipedia/Data/OldDataSchemaMigrator.m
@@ -1,76 +1,115 @@
-//
-//  OldDataSchema.m
-//  OldDataSchema
-//
-//  Created by Brion on 12/22/14.
-//  Copyright (c) 2014 Wikimedia Foundation. All rights reserved.
-//
 
 #import "OldDataSchemaMigrator_Private.h"
 #import "ArticleCoreDataObjects.h"
 #import "NSDateFormatter+WMFExtensions.h"
-#import "ArticleDataContextSingleton.h"
 #import "NSManagedObjectContext+SimpleFetch.h"
 #import "Article+ConvenienceAccessors.h"
 
+static NSString* const kWMFOldDataSchemaBackupDateKey               = 
@"kWMFOldDataSchemaBackupDateKey";
+static NSUInteger const kWMFOldDataSchemaBackupExpirationTimeInDays = 30;
+
+
 @interface OldDataSchemaMigrator ()
 
-@property (nonatomic, strong) ArticleDataContextSingleton* context;
+@property (nonatomic, strong, readwrite) NSString* databasePath;
+
 @property (nonatomic, strong) NSMutableSet* savedTitles;
 
 @end
 
 @implementation OldDataSchemaMigrator
 
-- (instancetype)init {
+- (instancetype)initWithDatabasePath:(NSString*)databasePath {
     self = [super init];
     if (self) {
-        _savedTitles = [[NSMutableSet alloc] init];
-        if ([[self class] exists]) {
-            _context = [ArticleDataContextSingleton sharedInstance];
-        } else {
-            _context = nil;
-        }
+        self.savedTitles  = [[NSMutableSet alloc] init];
+        self.databasePath = databasePath;
     }
     return self;
 }
 
-+ (NSString*)sqlitePath {
-    NSArray* documentPaths     = 
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
-    NSString* documentRootPath = [documentPaths objectAtIndex:0];
-    NSString* filePath         = [documentRootPath 
stringByAppendingPathComponent:@"articleData6.sqlite"];
-    return filePath;
+- (NSString*)backupDatabasePath {
+    return [self.databasePath stringByAppendingString:@".bak"];
 }
 
-+ (BOOL)exists {
-    NSString* filePath = [self sqlitePath];
-    return [[NSFileManager defaultManager] fileExistsAtPath:filePath];
+- (BOOL)exists {
+    return [[NSFileManager defaultManager] fileExistsAtPath:self.databasePath];
 }
 
-+ (void)removeOldData {
-    NSString* filePath   = [self sqlitePath];
-    NSString* backupPath = [filePath stringByAppendingString:@".bak"];
-    NSError* err         = nil;
-    [[NSFileManager defaultManager] moveItemAtPath:filePath
-                                            toPath:backupPath
-                                             error:&err];
-    if (err) {
-        NSLog(@"Error backing up %@: %@", filePath, err);
+- (BOOL)backupExists {
+    return [[NSFileManager defaultManager] fileExistsAtPath:[self 
backupDatabasePath]];
+}
+
+- (BOOL)moveOldDataToBackupLocation {
+    NSError* err = nil;
+
+    if ([[NSFileManager defaultManager] moveItemAtPath:self.databasePath
+                                                toPath:[self 
backupDatabasePath]
+                                                 error:&err]) {
+        [self setBackDateToNow];
+        return YES;
+    } else {
+        NSLog(@"Error backing up %@: %@", self.databasePath, err);
+        return NO;
     }
 }
 
+- (BOOL)removeOldDataIfOlderThanMaximumGracePeriod {
+    [self setBackupDateForPreexistingBackups];
+
+    if ([self shouldRemoveBackup]) {
+        return [self removebackupDataImmediately];
+    }
+
+    return NO;
+}
+
+- (BOOL)removebackupDataImmediately {
+    NSError* error = nil;
+
+    if ([[NSFileManager defaultManager] removeItemAtPath:[self 
backupDatabasePath] error:&error]) {
+        return YES;
+    } else {
+        NSLog(@"Error removing backup %@: %@", [self backupDatabasePath], 
[error localizedDescription]);
+        return NO;
+    }
+}
+
+- (void)setBackDateToNow {
+    NSDate* backupDate = [NSDate new];
+    [[NSUserDefaults standardUserDefaults] 
setDouble:backupDate.timeIntervalSinceReferenceDate 
forKey:kWMFOldDataSchemaBackupDateKey];
+    [[NSUserDefaults standardUserDefaults] synchronize];
+}
+
+- (void)setBackupDateForPreexistingBackups {
+    if (([[NSUserDefaults standardUserDefaults] 
doubleForKey:kWMFOldDataSchemaBackupDateKey] < 1.0) && [self backupExists]) {
+        [self setBackDateToNow];
+    }
+}
+
+- (BOOL)shouldRemoveBackup {
+    NSTimeInterval backupTimeInterval = [[NSUserDefaults standardUserDefaults] 
doubleForKey:kWMFOldDataSchemaBackupDateKey];
+    if (backupTimeInterval < 1.0) {
+        return NO;
+    }
+
+    NSDate* backupDate = [NSDate 
dateWithTimeIntervalSinceReferenceDate:backupTimeInterval];
+
+    NSTimeInterval backupExpiraton = 
kWMFOldDataSchemaBackupExpirationTimeInDays * 24 * 60 * 60;
+
+    if ([[NSDate new] timeIntervalSinceDate:backupDate] > backupExpiraton) {
+        return YES;
+    }
+
+    return NO;
+}
+
 - (void)migrateData {
-    // TODO
-    // 1) Go through saved article list, saving entries and (articles and 
images)
-    // 2) Go through page reading history, saving entries and (articles and 
images) when not already transferred
-
-    NSManagedObjectContext* context = [self.context backgroundContext];
-
-    [context performBlock:^{
+    [self.context performBlock:^{
         NSFetchRequest* req = [NSFetchRequest 
fetchRequestWithEntityName:@"Saved"];
         req.sortDescriptors = @[[[NSSortDescriptor alloc] 
initWithKey:@"dateSaved" ascending:YES]];
         NSError* err;
-        NSArray* savedEntries = [context executeFetchRequest:req error:&err];
+        NSArray* savedEntries = [self.context executeFetchRequest:req 
error:&err];
 
         if (err) {
             NSLog(@"Error reading old Saved entries: %@", err);
@@ -79,7 +118,7 @@
         NSFetchRequest* req2 = [NSFetchRequest 
fetchRequestWithEntityName:@"History"];
         req2.sortDescriptors = @[[[NSSortDescriptor alloc] 
initWithKey:@"dateVisited" ascending:YES]];
         NSError* err2;
-        NSArray* historyEntries = [context executeFetchRequest:req2 
error:&err2];
+        NSArray* historyEntries = [self.context executeFetchRequest:req2 
error:&err2];
 
         if (err2) {
             NSLog(@"Error reading old History entries: %@", err2);
@@ -105,15 +144,8 @@
             incrementAndNotify();
         }
 
-        [self.context saveContextAndPropagateChangesToStore:context 
completionBlock:^(NSError* error) {
-            [[self class] removeOldData];
-
-            if (error) {
-                [self.progressDelegate oldDataSchema:self 
didFinishWithError:error];
-            } else {
-                [self.progressDelegate oldDataSchemaDidFinishMigration:self];
-            }
-        }];
+        [self moveOldDataToBackupLocation];
+        [self.progressDelegate oldDataSchemaDidFinishMigration:self];
     }];
 }
 
diff --git a/Wikipedia/Data/OldDataSchemaMigrator_Private.h 
b/Wikipedia/Data/OldDataSchemaMigrator_Private.h
index fd352bb..2a0221f 100644
--- a/Wikipedia/Data/OldDataSchemaMigrator_Private.h
+++ b/Wikipedia/Data/OldDataSchemaMigrator_Private.h
@@ -1,10 +1,3 @@
-//
-//  OldDataSchemaMigrator_Private.h
-//  Wikipedia
-//
-//  Created by Brian Gerstle on 3/21/15.
-//  Copyright (c) 2015 Wikimedia Foundation. All rights reserved.
-//
 
 #import "OldDataSchemaMigrator.h"
 #import "ArticleCoreDataObjects.h"
diff --git a/Wikipedia/View 
Controllers/DataMigration/DataMigrationProgressViewController.h 
b/Wikipedia/View Controllers/DataMigration/DataMigrationProgressViewController.h
index cb3a248..c99b9fa 100644
--- a/Wikipedia/View 
Controllers/DataMigration/DataMigrationProgressViewController.h
+++ b/Wikipedia/View 
Controllers/DataMigration/DataMigrationProgressViewController.h
@@ -1,10 +1,3 @@
-//
-//  DataMigrationProgress.h
-//  Wikipedia
-//
-//  Created by Brion on 1/13/15.
-//  Copyright (c) 2015 Wikimedia Foundation. All rights reserved.
-//
 
 #import <UIKit/UIKit.h>
 #import <MessageUI/MessageUI.h>
@@ -23,8 +16,13 @@
 @property (weak, nonatomic) IBOutlet UILabel* progressLabel;
 @property (weak, nonatomic) id<DataMigrationProgressDelegate> delegate;
 
-// TODO: refactor these into class methods
-+ (BOOL)needsMigration;
-+ (void)removeOldData;
+- (BOOL)needsMigration;
+
+
+- (void)moveOldDataToBackupLocation;
+
+
+- (void)removeOldDataBackupIfNeeded;
+
 
 @end
diff --git a/Wikipedia/View 
Controllers/DataMigration/DataMigrationProgressViewController.m 
b/Wikipedia/View Controllers/DataMigration/DataMigrationProgressViewController.m
index 654217e..75fa844 100644
--- a/Wikipedia/View 
Controllers/DataMigration/DataMigrationProgressViewController.m
+++ b/Wikipedia/View 
Controllers/DataMigration/DataMigrationProgressViewController.m
@@ -1,10 +1,3 @@
-//
-//  DataMigrationProgress.m
-//  Wikipedia
-//
-//  Created by Brion on 1/13/15.
-//  Copyright (c) 2015 Wikimedia Foundation. All rights reserved.
-//
 
 #import "DataMigrationProgressViewController.h"
 
@@ -18,6 +11,7 @@
 
 #import "WikipediaAppUtils.h"
 #import "WMFProgressLineView.h"
+#import "ArticleDataContextSingleton.h"
 
 enum {
     BUTTON_INDEX_DISCARD = 0,
@@ -49,7 +43,7 @@
 - (void)viewDidAppear:(BOOL)animated {
     [super viewDidAppear:animated];
 
-    if ([OldDataSchemaMigrator exists]) {
+    if ([self.oldDataSchema exists]) {
         [self runNewMigration];
     } else if ([DataMigrator hasData]) {
         [self runOldMigration];
@@ -58,7 +52,8 @@
 
 - (OldDataSchemaMigrator*)oldDataSchema {
     if (_oldDataSchema == nil) {
-        _oldDataSchema = [[OldDataSchemaMigrator alloc] init];
+        ArticleDataContextSingleton* context = [ArticleDataContextSingleton 
sharedInstance];
+        _oldDataSchema = [[OldDataSchemaMigrator alloc] 
initWithDatabasePath:context.databasePath];
     }
     return _oldDataSchema;
 }
@@ -77,13 +72,17 @@
     return _schemaConvertor;
 }
 
-+ (BOOL)needsMigration {
-    return [OldDataSchemaMigrator exists] || [DataMigrator hasData];
+- (BOOL)needsMigration {
+    return [self.oldDataSchema exists] || [DataMigrator hasData];
 }
 
-+ (void)removeOldData {
-    [DataMigrator removeOldData];
-    [OldDataSchemaMigrator removeOldData];
+- (void)moveOldDataToBackupLocation {
+    [DataMigrator removeOldData]; //we do not back old old data
+    [self.oldDataSchema moveOldDataToBackupLocation];
+}
+
+- (void)removeOldDataBackupIfNeeded {
+    [self.oldDataSchema removeOldDataIfOlderThanMaximumGracePeriod];
 }
 
 - (void)runNewMigration {
@@ -95,6 +94,7 @@
 
     self.oldDataSchema.delegate         = self.schemaConvertor;
     self.oldDataSchema.progressDelegate = self;
+    self.oldDataSchema.context          = [[ArticleDataContextSingleton 
sharedInstance] backgroundContext];
     NSLog(@"begin migration");
     [self.oldDataSchema migrateData];
 }
@@ -178,10 +178,10 @@
 
 - (void)submitDataToDevs {
     MFMailComposeViewController* picker = [[MFMailComposeViewController alloc] 
init];
-    picker.mailComposeDelegate = self; //
+    picker.mailComposeDelegate = self;
 
-    picker.subject      = @"Wikipedia iOS app data migration failure";
-    picker.toRecipients = @[@"bvib...@wikimedia.org"]; // @fixme do we have a 
better place to send these?
+    picker.subject      = [NSString stringWithFormat:@"Feedback:%@", 
[WikipediaAppUtils versionedUserAgent]];
+    picker.toRecipients = @[@"mobile-ios-wikipe...@wikimedia.org"];
 
     NSString* filename         = @"articleData6.sqlite";
     NSArray* documentPaths     = 
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
diff --git a/Wikipedia/mw-utils/WikipediaAppUtils.m 
b/Wikipedia/mw-utils/WikipediaAppUtils.m
index c471c2a..086a629 100644
--- a/Wikipedia/mw-utils/WikipediaAppUtils.m
+++ b/Wikipedia/mw-utils/WikipediaAppUtils.m
@@ -51,7 +51,7 @@
 + (NSString*)versionedUserAgent {
     UIDevice* d = [UIDevice currentDevice];
     return [NSString stringWithFormat:@"WikipediaApp/%@ (%@ %@; %@)",
-            [self appVersion],
+            [[NSBundle mainBundle] wmf_debugVersion],
             [d systemName],
             [d systemVersion],
             [self formFactor]
diff --git a/WikipediaUnitTests/OldDataSchemaMigratorTests.m 
b/WikipediaUnitTests/OldDataSchemaMigratorTests.m
index f9e5cb9..7439be1 100644
--- a/WikipediaUnitTests/OldDataSchemaMigratorTests.m
+++ b/WikipediaUnitTests/OldDataSchemaMigratorTests.m
@@ -43,7 +43,9 @@
     self.migrator.delegate = self.converter;
 
     // objects must be inserted into a MOC in order for (inverse) 
relationships to be maintained automatically
+//    self.tmpContext = [NSManagedObjectContext 
wmf_tempContextInBundle:[NSBundle bundleForClass:[self class]]];
     self.tmpContext = [NSManagedObjectContext wmf_tempContext];
+
 }
 
 - (void)tearDown {
@@ -97,8 +99,38 @@
     [self verifySkippedMigrationOfArticle:oldArticle];
 }
 
+//- (void)testBackingUpStore{
+//    
+//    NSString* path = [self databasePathForContext:self.tmpContext];
+//    
+//    OldDataSchemaMigrator* oldDataSchema = [[OldDataSchemaMigrator alloc] 
initWithDatabasePath:path];
+//    
+//    XCTAssertTrue([oldDataSchema moveOldDataToBackupLocation],
+//                  @"Backup was not moved!");
+//    
+//}
+//
+//
+//- (void)testRemovingBackupStore{
+//    
+//    NSString* path = [self databasePathForContext:self.tmpContext];
+//    
+//    OldDataSchemaMigrator* oldDataSchema = [[OldDataSchemaMigrator alloc] 
initWithDatabasePath:path];
+//    
+//    [oldDataSchema moveOldDataToBackupLocation];
+//    
+//    XCTAssertTrue([oldDataSchema removebackupDataImmediately],
+//                   @"Store was not removed!");
+//
+//}
+
 #pragma mark - Test Utils
 
+- (NSString*)databasePathForContext:(NSManagedObjectContext*)context{
+    
+    return [[[[[context persistentStoreCoordinator] persistentStores] 
firstObject] URL] absoluteString];
+}
+
 - (void)verifySkippedMigrationOfArticle:(Article*)oldArticle {
     XCTAssertNoThrow([self.migrator migrateArticle:oldArticle],
                      @"Failed to catch an article migration exception.");

-- 
To view, visit https://gerrit.wikimedia.org/r/209024
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I2c9dccbfb04803dc4d80ee8dcae64b76f13a39e3
Gerrit-PatchSet: 5
Gerrit-Project: apps/ios/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Fjalapeno <cfl...@wikimedia.org>
Gerrit-Reviewer: Bgerstle <bgers...@wikimedia.org>
Gerrit-Reviewer: Dr0ptp4kt <ab...@wikimedia.org>
Gerrit-Reviewer: Fjalapeno <cfl...@wikimedia.org>
Gerrit-Reviewer: Mhurd <mh...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to