mirror of
https://github.com/nextcloud/android.git
synced 2024-11-23 21:55:48 +03:00
Fixed database update due to renaming folders
This commit is contained in:
parent
85e9a40dbe
commit
d0b7df16e7
5 changed files with 125 additions and 26 deletions
|
@ -42,4 +42,6 @@ public interface DataStorageManager {
|
|||
public void removeFile(OCFile file, boolean removeLocalCopy);
|
||||
|
||||
public void removeDirectory(OCFile dir, boolean removeDBData, boolean removeLocalContent);
|
||||
|
||||
public void moveDirectory(OCFile dir, String newPath);
|
||||
}
|
||||
|
|
|
@ -500,5 +500,76 @@ public class FileDataStorageManager implements DataStorageManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates database for a folder that was moved to a different location.
|
||||
*
|
||||
* TODO explore better (faster) implementations
|
||||
* TODO throw exceptions up !
|
||||
*/
|
||||
@Override
|
||||
public void moveDirectory(OCFile dir, String newPath) {
|
||||
// TODO check newPath
|
||||
|
||||
if (dir != null && dir.isDirectory() && dir.fileExists() && !dir.getFileName().equals(OCFile.PATH_SEPARATOR)) {
|
||||
/// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
|
||||
Cursor c = null;
|
||||
if (getContentProvider() != null) {
|
||||
try {
|
||||
c = getContentProvider().query(ProviderTableMeta.CONTENT_URI,
|
||||
null,
|
||||
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ?",
|
||||
new String[] { mAccount.name, dir.getRemotePath() + "%" }, null);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
c = getContentResolver().query(ProviderTableMeta.CONTENT_URI,
|
||||
null,
|
||||
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ?",
|
||||
new String[] { mAccount.name, dir.getRemotePath() + "%" }, null);
|
||||
}
|
||||
|
||||
/// 2. prepare a batch of update operations to change all the descendants
|
||||
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(c.getCount());
|
||||
ContentValues cv = new ContentValues();
|
||||
int lengthOfOldPath = dir.getRemotePath().length();
|
||||
String defaultSavePath = FileDownloader.getSavePath(mAccount.name);
|
||||
int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
|
||||
if (c.moveToFirst()) {
|
||||
do {
|
||||
OCFile child = createFileInstance(c);
|
||||
cv.put(ProviderTableMeta.FILE_PATH, newPath + child.getRemotePath().substring(lengthOfOldPath));
|
||||
if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) {
|
||||
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath));
|
||||
}
|
||||
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
|
||||
withValues(cv).
|
||||
withSelection( ProviderTableMeta._ID + "=?",
|
||||
new String[] { String.valueOf(child.getFileId()) })
|
||||
.build());
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
c.close();
|
||||
|
||||
/// 3. apply updates in batch
|
||||
try {
|
||||
if (getContentResolver() != null) {
|
||||
getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
|
||||
|
||||
} else {
|
||||
getContentProvider().applyBatch(operations);
|
||||
}
|
||||
|
||||
} catch (OperationApplicationException e) {
|
||||
Log.e(TAG, "Fail to update descendants of " + dir.getFileId() + " in database", e);
|
||||
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Fail to update desendants of " + dir.getFileId() + " in database", e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.io.IOException;
|
|||
import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
|
||||
//import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.datamodel.DataStorageManager;
|
||||
|
@ -48,7 +49,9 @@ public class RenameFileOperation extends RemoteOperation {
|
|||
|
||||
|
||||
private OCFile mFile;
|
||||
private Account mAccount;
|
||||
private String mNewName;
|
||||
private String mNewRemotePath;
|
||||
private DataStorageManager mStorageManager;
|
||||
|
||||
|
||||
|
@ -56,12 +59,15 @@ public class RenameFileOperation extends RemoteOperation {
|
|||
* Constructor
|
||||
*
|
||||
* @param file OCFile instance describing the remote file or folder to rename
|
||||
* @param account OwnCloud account containing the remote file
|
||||
* @param newName New name to set as the name of file.
|
||||
* @param storageManager Reference to the local database corresponding to the account where the file is contained.
|
||||
*/
|
||||
public RenameFileOperation(OCFile file, String newName, DataStorageManager storageManager) {
|
||||
public RenameFileOperation(OCFile file, Account account, String newName, DataStorageManager storageManager) {
|
||||
mFile = file;
|
||||
mAccount = account;
|
||||
mNewName = newName;
|
||||
mNewRemotePath = null;
|
||||
mStorageManager = storageManager;
|
||||
}
|
||||
|
||||
|
@ -80,7 +86,7 @@ public class RenameFileOperation extends RemoteOperation {
|
|||
RemoteOperationResult result = null;
|
||||
|
||||
LocalMoveMethod move = null;
|
||||
String newRemotePath = null;
|
||||
mNewRemotePath = null;
|
||||
try {
|
||||
if (mNewName.equals(mFile.getFileName())) {
|
||||
return new RemoteOperationResult(ResultCode.OK);
|
||||
|
@ -88,7 +94,10 @@ public class RenameFileOperation extends RemoteOperation {
|
|||
|
||||
String parent = (new File(mFile.getRemotePath())).getParent();
|
||||
parent = (parent.endsWith(OCFile.PATH_SEPARATOR)) ? parent : parent + OCFile.PATH_SEPARATOR;
|
||||
newRemotePath = parent + mNewName;
|
||||
mNewRemotePath = parent + mNewName;
|
||||
if (mFile.isDirectory()) {
|
||||
mNewRemotePath += OCFile.PATH_SEPARATOR;
|
||||
}
|
||||
|
||||
// check if the new name is valid in the local file system
|
||||
if (!isValidNewName()) {
|
||||
|
@ -96,34 +105,22 @@ public class RenameFileOperation extends RemoteOperation {
|
|||
}
|
||||
|
||||
// check if a file with the new name already exists
|
||||
if (client.existsFile(newRemotePath) || // remote check could fail by network failure, or by indeterminate behavior of HEAD for folders ...
|
||||
mStorageManager.getFileByPath(newRemotePath) != null) { // ... so local check is convenient
|
||||
if (client.existsFile(mNewRemotePath) || // remote check could fail by network failure, or by indeterminate behavior of HEAD for folders ...
|
||||
mStorageManager.getFileByPath(mNewRemotePath) != null) { // ... so local check is convenient
|
||||
return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
|
||||
}
|
||||
move = new LocalMoveMethod( client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath()),
|
||||
client.getBaseUri() + WebdavUtils.encodePath(newRemotePath));
|
||||
client.getBaseUri() + WebdavUtils.encodePath(mNewRemotePath));
|
||||
int status = client.executeMethod(move, RENAME_READ_TIMEOUT, RENAME_CONNECTION_TIMEOUT);
|
||||
if (move.succeeded()) {
|
||||
|
||||
// create new OCFile instance for the renamed file
|
||||
/*OCFile newFile = new OCFile(mStorageManager.getFileById(mFile.getParentId()).getRemotePath() + mNewName; // TODO - NOT CREATE NEW OCFILE; ADD setFileName METHOD
|
||||
OCFile oldFile = mFile;
|
||||
mFile = newFile; */
|
||||
mFile.setFileName(mNewName);
|
||||
|
||||
// try to rename the local copy of the file
|
||||
if (mFile.isDown()) {
|
||||
File f = new File(mFile.getStoragePath());
|
||||
String newStoragePath = f.getParent() + mNewName;
|
||||
if (f.renameTo(new File(newStoragePath))) {
|
||||
mFile.setStoragePath(newStoragePath);
|
||||
}
|
||||
// else - NOTHING: the link to the local file is kept although the local name can't be updated
|
||||
// TODO - study conditions when this could be a problem
|
||||
if (mFile.isDirectory()) {
|
||||
saveLocalDirectory();
|
||||
|
||||
} else {
|
||||
saveLocalFile();
|
||||
|
||||
}
|
||||
|
||||
//mStorageManager.removeFile(oldFile, false);
|
||||
mStorageManager.saveFile(mFile);
|
||||
|
||||
/*
|
||||
*} else if (mFile.isDirectory() && (status == 207 || status >= 500)) {
|
||||
|
@ -141,11 +138,11 @@ public class RenameFileOperation extends RemoteOperation {
|
|||
|
||||
move.getResponseBodyAsString(); // exhaust response, although not interesting
|
||||
result = new RemoteOperationResult(move.succeeded(), status);
|
||||
Log.i(TAG, "Rename " + mFile.getRemotePath() + " to " + newRemotePath + ": " + result.getLogMessage());
|
||||
Log.i(TAG, "Rename " + mFile.getRemotePath() + " to " + mNewRemotePath + ": " + result.getLogMessage());
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult(e);
|
||||
Log.e(TAG, "Rename " + mFile.getRemotePath() + " to " + ((newRemotePath==null) ? mNewName : newRemotePath) + ": " + result.getLogMessage(), e);
|
||||
Log.e(TAG, "Rename " + mFile.getRemotePath() + " to " + ((mNewRemotePath==null) ? mNewName : mNewRemotePath) + ": " + result.getLogMessage(), e);
|
||||
|
||||
} finally {
|
||||
if (move != null)
|
||||
|
@ -155,6 +152,33 @@ public class RenameFileOperation extends RemoteOperation {
|
|||
}
|
||||
|
||||
|
||||
private void saveLocalDirectory() {
|
||||
mStorageManager.moveDirectory(mFile, mNewRemotePath);
|
||||
String localPath = FileDownloader.getSavePath(mAccount.name) + mFile.getRemotePath();
|
||||
File localDir = new File(localPath);
|
||||
if (localDir.exists()) {
|
||||
localDir.renameTo(new File(FileDownloader.getSavePath(mAccount.name) + mNewRemotePath));
|
||||
// TODO - if renameTo fails, children files that are already down will result unlinked
|
||||
}
|
||||
}
|
||||
|
||||
private void saveLocalFile() {
|
||||
mFile.setFileName(mNewName);
|
||||
|
||||
// try to rename the local copy of the file
|
||||
if (mFile.isDown()) {
|
||||
File f = new File(mFile.getStoragePath());
|
||||
String newStoragePath = f.getParent() + mNewName;
|
||||
if (f.renameTo(new File(newStoragePath))) {
|
||||
mFile.setStoragePath(newStoragePath);
|
||||
}
|
||||
// else - NOTHING: the link to the local file is kept although the local name can't be updated
|
||||
// TODO - study conditions when this could be a problem
|
||||
}
|
||||
|
||||
mStorageManager.saveFile(mFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the new name to set is valid in the file system
|
||||
*
|
||||
|
|
|
@ -829,6 +829,7 @@ public class FileDetailFragment extends SherlockFragment implements
|
|||
String newFilename = dialog.getNewFilename();
|
||||
Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
|
||||
mLastRemoteOperation = new RenameFileOperation( mFile,
|
||||
mAccount,
|
||||
newFilename,
|
||||
new FileDataStorageManager(mAccount, getActivity().getContentResolver()));
|
||||
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
|
||||
|
|
|
@ -441,6 +441,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
|
|||
String newFilename = dialog.getNewFilename();
|
||||
Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
|
||||
RemoteOperation operation = new RenameFileOperation(mTargetFile,
|
||||
AccountUtils.getCurrentOwnCloudAccount(getActivity()),
|
||||
newFilename,
|
||||
mContainerActivity.getStorageManager());
|
||||
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity().getApplicationContext());
|
||||
|
|
Loading…
Reference in a new issue