public static AtomicAction MoveDirectory(string srcPath, string dstPath)
 {
     var seq = new AtomicAction();
     seq.AddLogic(AtomicAction.DeleteDirectory(dstPath));
     seq.AddLogic(AtomicAction.MoveDirectoryUnsafe(srcPath, dstPath));
     return seq;
 }
        public static AtomicAction MoveDirectory(string srcPath, string dstPath)
        {
            var seq = new AtomicAction();

            seq.AddLogic(AtomicAction.DeleteDirectory(dstPath));
            seq.AddLogic(AtomicAction.MoveDirectoryUnsafe(srcPath, dstPath));
            return(seq);
        }
        public AtomicAction ActionToChangeEncryptionKey(SymmetricKey newKey)
        {
            var retVal = new AtomicAction(() =>
                ForestDBBridge.Check(err => 
                {
                    var newc4key = default(C4EncryptionKey);
                    if (newKey != null) {
                        newc4key = new C4EncryptionKey(newKey.KeyData);
                    }

                    return Native.c4db_rekey(Forest, &newc4key, err);
                }), null, null);

            foreach (var viewName in GetAllViews()) {
                var store = GetViewStorage(viewName, false) as ForestDBViewStore;
                if (store == null) {
                    continue;
                }

                retVal.AddLogic(store.ActionToChangeEncryptionKey(newKey));
            }

            return retVal;
        }
        public AtomicAction ActionToChangeEncryptionKey(SymmetricKey newKey)
        {
            var action = new AtomicAction();

            // Find all the blob files:
            var blobs = default(string[]);
            var oldKey = EncryptionKey;
            blobs = Directory.GetFiles(_path, "*" + FileExtension);
            if (blobs.Length == 0) {
                // No blobs, so nothing to encrypt. Just add/remove the encryption marker file:
                action.AddLogic(() =>
                {
                    Log.To.NoDomain.D(TAG, "{0} {1}", (newKey != null) ? "encrypting" : "decrypting", _path);
                    Log.To.NoDomain.D(TAG, "    No blobs to copy; done.");
                    EncryptionKey = newKey;
                    MarkEncrypted(newKey != null);
                }, () =>
                {
                    EncryptionKey = oldKey;
                    MarkEncrypted(oldKey != null);
                }, null);
                return action;
            }

            // Create a new directory for the new blob store. Have to do this now, before starting the
            // action, because farther down we create an action to move it...
            var tempPath = Path.Combine(Path.GetTempPath(), String.Format("CouchbaseLite-Temp-{0}", Misc.CreateGUID()));
            action.AddLogic(() => 
            {
                Log.To.NoDomain.D(TAG, "{0} {1}", (newKey != null) ? "encrypting" : "decrypting", _path);
                Directory.CreateDirectory(tempPath);
            }, () => Directory.Delete(tempPath, true), null);

            var tempStore = default(BlobStore);
            action.AddLogic(() =>
            {
                tempStore = new BlobStore(tempPath, newKey);
                tempStore.MarkEncrypted(true);
            }, null, null);

            // Copy each of my blobs into the new store (which will update its encryption):
            action.AddLogic(() =>
            {
                foreach(var blobName in blobs) {
                    // Copy file by reading with old key and writing with new one:
                    Log.To.NoDomain.D(TAG, "    Copying {0}", blobName);
                    Stream readStream = File.Open(blobName, FileMode.Open, FileAccess.Read, FileShare.Read);
                    if(EncryptionKey != null) {
                        readStream = EncryptionKey.DecryptStream(readStream);
                    }

                    var writer = new BlobStoreWriter(tempStore);
                    try {
                        writer.Read(readStream);
                        writer.Finish();
                        writer.Install();
                    } catch(Exception) {
                        writer.Cancel();
                        throw;
                    } finally {
                        readStream.Dispose();
                    }
                }
            }, null, null);

            // Replace the attachment dir with the new one:
            action.AddLogic(AtomicAction.MoveDirectory(tempPath, _path));

            // Finally update EncryptionKey:
            action.AddLogic(() =>
            {
                EncryptionKey = newKey;
            }, () =>
            {
                EncryptionKey = oldKey;
            }, null);

            return action;
        }