mirror of
https://github.com/nextcloud/android.git
synced 2024-11-24 06:05:42 +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 removeFile(OCFile file, boolean removeLocalCopy);
|
||||||
|
|
||||||
public void removeDirectory(OCFile dir, boolean removeDBData, boolean removeLocalContent);
|
public void removeDirectory(OCFile dir, boolean removeDBData, boolean removeLocalContent);
|
||||||
|
|
||||||
|
public void moveDirectory(OCFile dir, String newPath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -501,4 +501,75 @@ 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.DavMethodBase;
|
||||||
//import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
|
//import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.owncloud.android.datamodel.DataStorageManager;
|
import com.owncloud.android.datamodel.DataStorageManager;
|
||||||
|
@ -48,7 +49,9 @@ public class RenameFileOperation extends RemoteOperation {
|
||||||
|
|
||||||
|
|
||||||
private OCFile mFile;
|
private OCFile mFile;
|
||||||
|
private Account mAccount;
|
||||||
private String mNewName;
|
private String mNewName;
|
||||||
|
private String mNewRemotePath;
|
||||||
private DataStorageManager mStorageManager;
|
private DataStorageManager mStorageManager;
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,12 +59,15 @@ public class RenameFileOperation extends RemoteOperation {
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param file OCFile instance describing the remote file or folder to rename
|
* @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 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.
|
* @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;
|
mFile = file;
|
||||||
|
mAccount = account;
|
||||||
mNewName = newName;
|
mNewName = newName;
|
||||||
|
mNewRemotePath = null;
|
||||||
mStorageManager = storageManager;
|
mStorageManager = storageManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +86,7 @@ public class RenameFileOperation extends RemoteOperation {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult result = null;
|
||||||
|
|
||||||
LocalMoveMethod move = null;
|
LocalMoveMethod move = null;
|
||||||
String newRemotePath = null;
|
mNewRemotePath = null;
|
||||||
try {
|
try {
|
||||||
if (mNewName.equals(mFile.getFileName())) {
|
if (mNewName.equals(mFile.getFileName())) {
|
||||||
return new RemoteOperationResult(ResultCode.OK);
|
return new RemoteOperationResult(ResultCode.OK);
|
||||||
|
@ -88,7 +94,10 @@ public class RenameFileOperation extends RemoteOperation {
|
||||||
|
|
||||||
String parent = (new File(mFile.getRemotePath())).getParent();
|
String parent = (new File(mFile.getRemotePath())).getParent();
|
||||||
parent = (parent.endsWith(OCFile.PATH_SEPARATOR)) ? parent : parent + OCFile.PATH_SEPARATOR;
|
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
|
// check if the new name is valid in the local file system
|
||||||
if (!isValidNewName()) {
|
if (!isValidNewName()) {
|
||||||
|
@ -96,35 +105,23 @@ public class RenameFileOperation extends RemoteOperation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a file with the new name already exists
|
// 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 ...
|
if (client.existsFile(mNewRemotePath) || // remote check could fail by network failure, or by indeterminate behavior of HEAD for folders ...
|
||||||
mStorageManager.getFileByPath(newRemotePath) != null) { // ... so local check is convenient
|
mStorageManager.getFileByPath(mNewRemotePath) != null) { // ... so local check is convenient
|
||||||
return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
|
return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
|
||||||
}
|
}
|
||||||
move = new LocalMoveMethod( client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath()),
|
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);
|
int status = client.executeMethod(move, RENAME_READ_TIMEOUT, RENAME_CONNECTION_TIMEOUT);
|
||||||
if (move.succeeded()) {
|
if (move.succeeded()) {
|
||||||
|
|
||||||
// create new OCFile instance for the renamed file
|
if (mFile.isDirectory()) {
|
||||||
/*OCFile newFile = new OCFile(mStorageManager.getFileById(mFile.getParentId()).getRemotePath() + mNewName; // TODO - NOT CREATE NEW OCFILE; ADD setFileName METHOD
|
saveLocalDirectory();
|
||||||
OCFile oldFile = mFile;
|
|
||||||
mFile = newFile; */
|
} else {
|
||||||
mFile.setFileName(mNewName);
|
saveLocalFile();
|
||||||
|
|
||||||
// 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.removeFile(oldFile, false);
|
|
||||||
mStorageManager.saveFile(mFile);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*} else if (mFile.isDirectory() && (status == 207 || status >= 500)) {
|
*} else if (mFile.isDirectory() && (status == 207 || status >= 500)) {
|
||||||
* // TODO
|
* // TODO
|
||||||
|
@ -141,11 +138,11 @@ public class RenameFileOperation extends RemoteOperation {
|
||||||
|
|
||||||
move.getResponseBodyAsString(); // exhaust response, although not interesting
|
move.getResponseBodyAsString(); // exhaust response, although not interesting
|
||||||
result = new RemoteOperationResult(move.succeeded(), status);
|
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) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(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 {
|
} finally {
|
||||||
if (move != null)
|
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
|
* 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();
|
String newFilename = dialog.getNewFilename();
|
||||||
Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
|
Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
|
||||||
mLastRemoteOperation = new RenameFileOperation( mFile,
|
mLastRemoteOperation = new RenameFileOperation( mFile,
|
||||||
|
mAccount,
|
||||||
newFilename,
|
newFilename,
|
||||||
new FileDataStorageManager(mAccount, getActivity().getContentResolver()));
|
new FileDataStorageManager(mAccount, getActivity().getContentResolver()));
|
||||||
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
|
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
|
||||||
|
|
|
@ -441,6 +441,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
|
||||||
String newFilename = dialog.getNewFilename();
|
String newFilename = dialog.getNewFilename();
|
||||||
Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
|
Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
|
||||||
RemoteOperation operation = new RenameFileOperation(mTargetFile,
|
RemoteOperation operation = new RenameFileOperation(mTargetFile,
|
||||||
|
AccountUtils.getCurrentOwnCloudAccount(getActivity()),
|
||||||
newFilename,
|
newFilename,
|
||||||
mContainerActivity.getStorageManager());
|
mContainerActivity.getStorageManager());
|
||||||
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity().getApplicationContext());
|
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity().getApplicationContext());
|
||||||
|
|
Loading…
Reference in a new issue