mirror of
https://github.com/nextcloud/desktop.git
synced 2024-10-27 15:05:19 +03:00
Merge remote-tracking branch 'origin/hidden_file_handling'
This commit is contained in:
commit
0a6aa88d72
24 changed files with 346 additions and 164 deletions
|
@ -124,6 +124,8 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
|
|||
|
||||
ctx->abort = false;
|
||||
|
||||
ctx->ignore_hidden_files = true;
|
||||
|
||||
*csync = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
@ -435,6 +437,7 @@ static int _csync_treewalk_visitor(void *obj, void *data) {
|
|||
|
||||
trav.error_status = cur->error_status;
|
||||
trav.should_update_metadata = cur->should_update_metadata;
|
||||
trav.has_ignored_files = cur->has_ignored_files;
|
||||
|
||||
if( other_node ) {
|
||||
csync_file_stat_t *other_stat = (csync_file_stat_t*)other_node->data;
|
||||
|
@ -592,6 +595,7 @@ int csync_commit(CSYNC *ctx) {
|
|||
ctx->remote.read_from_db = 0;
|
||||
ctx->read_remote_from_db = true;
|
||||
ctx->db_is_empty = false;
|
||||
ctx->ignore_hidden_files = true; // do NOT sync hidden files by default.
|
||||
|
||||
|
||||
/* Create new trees */
|
||||
|
|
|
@ -49,41 +49,37 @@ struct csync_client_certs_s {
|
|||
char *certificatePasswd;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instruction enum. In the file traversal structure, it describes
|
||||
* the csync state of a file.
|
||||
*/
|
||||
enum csync_status_codes_e {
|
||||
CSYNC_STATUS_OK = 0,
|
||||
|
||||
CSYNC_STATUS_ERROR = 1024, /* don't use this code,
|
||||
*/
|
||||
CSYNC_STATUS_UNSUCCESSFUL,
|
||||
CSYNC_STATUS_NO_LOCK, /* OBSOLETE does not happen anymore */
|
||||
CSYNC_STATUS_STATEDB_LOAD_ERROR,
|
||||
CSYNC_STATUS_STATEDB_CORRUPTED,
|
||||
CSYNC_STATUS_NO_MODULE,
|
||||
CSYNC_STATUS_TIMESKEW, /* OBSOLETE */
|
||||
CSYNC_STATUS_UNSUCCESSFUL, /* Unspecific problem happend */
|
||||
CSYNC_STATUS_NO_LOCK, /* OBSOLETE does not happen anymore */
|
||||
CSYNC_STATUS_STATEDB_LOAD_ERROR, /* Statedb can not be loaded. */
|
||||
CSYNC_STATUS_STATEDB_CORRUPTED, /* Statedb is corrupted */
|
||||
CSYNC_STATUS_NO_MODULE, /* URL passed to csync does not start with owncloud:// or ownclouds:// */
|
||||
CSYNC_STATUS_TIMESKEW, /* OBSOLETE */
|
||||
CSYNC_STATUS_FILESYSTEM_UNKNOWN, /* UNUSED */
|
||||
CSYNC_STATUS_TREE_ERROR,
|
||||
CSYNC_STATUS_MEMORY_ERROR,
|
||||
CSYNC_STATUS_PARAM_ERROR,
|
||||
CSYNC_STATUS_UPDATE_ERROR,
|
||||
CSYNC_STATUS_RECONCILE_ERROR,
|
||||
CSYNC_STATUS_PROPAGATE_ERROR, /* OBSOLETE */
|
||||
CSYNC_STATUS_TREE_ERROR, /* csync trees could not be created */
|
||||
CSYNC_STATUS_MEMORY_ERROR, /* not enough memory problem */
|
||||
CSYNC_STATUS_PARAM_ERROR, /* parameter is zero where not expected */
|
||||
CSYNC_STATUS_UPDATE_ERROR, /* general update or discovery error */
|
||||
CSYNC_STATUS_RECONCILE_ERROR, /* general reconcile error */
|
||||
CSYNC_STATUS_PROPAGATE_ERROR, /* OBSOLETE */
|
||||
CSYNC_STATUS_REMOTE_ACCESS_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_REMOTE_CREATE_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_REMOTE_STAT_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_REMOTE_STAT_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_LOCAL_CREATE_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_LOCAL_STAT_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_PROXY_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_LOOKUP_ERROR,
|
||||
CSYNC_STATUS_SERVER_AUTH_ERROR,
|
||||
CSYNC_STATUS_PROXY_AUTH_ERROR,
|
||||
CSYNC_STATUS_CONNECT_ERROR,
|
||||
CSYNC_STATUS_TIMEOUT,
|
||||
CSYNC_STATUS_HTTP_ERROR,
|
||||
CSYNC_STATUS_PERMISSION_DENIED,
|
||||
CSYNC_STATUS_LOCAL_STAT_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_PROXY_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_LOOKUP_ERROR, /* Neon fails to find proxy. Almost OBSOLETE */
|
||||
CSYNC_STATUS_SERVER_AUTH_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_PROXY_AUTH_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_CONNECT_ERROR, /* neon driven connection failed */
|
||||
CSYNC_STATUS_TIMEOUT, /* UNUSED */
|
||||
CSYNC_STATUS_HTTP_ERROR, /* UNUSED */
|
||||
CSYNC_STATUS_PERMISSION_DENIED, /* */
|
||||
CSYNC_STATUS_NOT_FOUND,
|
||||
CSYNC_STATUS_FILE_EXISTS,
|
||||
CSYNC_STATUS_OUT_OF_SPACE,
|
||||
|
@ -103,7 +99,8 @@ enum csync_status_codes_e {
|
|||
CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST,
|
||||
CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS,
|
||||
CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME,
|
||||
CYSNC_STATUS_FILE_LOCKED_OR_OPEN
|
||||
CYSNC_STATUS_FILE_LOCKED_OR_OPEN,
|
||||
CSYNC_STATUS_INDIVIDUAL_EXCLUDE_HIDDEN
|
||||
};
|
||||
|
||||
typedef enum csync_status_codes_e CSYNC_STATUS;
|
||||
|
@ -119,7 +116,10 @@ typedef enum csync_status_codes_e CSYNC_STATUS;
|
|||
#define CSYNC_STATUS_IS_ERR(x) (unlikely((x) >= CSYNC_STATUS_ERROR))
|
||||
#define CSYNC_STATUS_IS_EQUAL(x, y) ((x) == (y))
|
||||
|
||||
|
||||
/**
|
||||
* Instruction enum. In the file traversal structure, it describes
|
||||
* the csync state of a file.
|
||||
*/
|
||||
enum csync_instructions_e {
|
||||
CSYNC_INSTRUCTION_NONE = 0x00000000, /* Nothing to do (UPDATE|RECONCILE) */
|
||||
CSYNC_INSTRUCTION_EVAL = 0x00000001, /* There was changed compared to the DB (UPDATE) */
|
||||
|
@ -249,6 +249,9 @@ struct csync_tree_walk_file_s {
|
|||
/* For directories: If the etag has been updated and need to be writen on the db */
|
||||
int should_update_metadata;
|
||||
|
||||
/* For directories: Does it have children that were ignored (hidden or ignore pattern) */
|
||||
int has_ignored_files;
|
||||
|
||||
const char *rename_path;
|
||||
const char *etag;
|
||||
const char *file_id;
|
||||
|
|
|
@ -27,7 +27,8 @@ enum csync_exclude_type_e {
|
|||
CSYNC_FILE_EXCLUDE_AND_REMOVE,
|
||||
CSYNC_FILE_EXCLUDE_LIST,
|
||||
CSYNC_FILE_EXCLUDE_INVALID_CHAR,
|
||||
CSYNC_FILE_EXCLUDE_LONG_FILENAME
|
||||
CSYNC_FILE_EXCLUDE_LONG_FILENAME,
|
||||
CSYNC_FILE_EXCLUDE_HIDDEN
|
||||
};
|
||||
typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
|
||||
|
||||
|
|
|
@ -168,6 +168,8 @@ struct csync_s {
|
|||
*/
|
||||
bool db_is_empty;
|
||||
|
||||
bool ignore_hidden_files;
|
||||
|
||||
struct csync_owncloud_ctx_s *owncloud_context;
|
||||
|
||||
};
|
||||
|
|
|
@ -283,6 +283,9 @@ static int _csync_file_stat_from_metadata_table( csync_file_stat_t **st, sqlite3
|
|||
if(column_count > 12 && sqlite3_column_int64(stmt,12)) {
|
||||
(*st)->size = sqlite3_column_int64(stmt, 12);
|
||||
}
|
||||
if(column_count > 13) {
|
||||
(*st)->has_ignored_files = sqlite3_column_int(stmt, 13);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if( rc != SQLITE_DONE ) {
|
||||
|
@ -435,7 +438,7 @@ char *csync_statedb_get_etag( CSYNC *ctx, uint64_t jHash ) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define BELOW_PATH_QUERY "SELECT phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize FROM metadata WHERE pathlen>? AND path LIKE(?)"
|
||||
#define BELOW_PATH_QUERY "SELECT phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote FROM metadata WHERE pathlen>? AND path LIKE(?)"
|
||||
|
||||
int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
int rc;
|
||||
|
|
|
@ -163,29 +163,27 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||
|
||||
len = strlen(path);
|
||||
|
||||
/* This code should probably be in csync_exclude, but it does not have the fs parameter.
|
||||
Keep it here for now and TODO also find out if we want this for Windows
|
||||
https://github.com/owncloud/mirall/issues/2086 */
|
||||
if (fs->flags & CSYNC_VIO_FILE_FLAGS_HIDDEN) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file excluded because it is a hidden file: %s", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if file is excluded */
|
||||
excluded = csync_excluded(ctx, path,type);
|
||||
|
||||
if (excluded != CSYNC_NOT_EXCLUDED) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", path, excluded);
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) {
|
||||
return 1;
|
||||
}
|
||||
if (excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ctx->current_fs) {
|
||||
ctx->current_fs->has_ignored_files = true;
|
||||
}
|
||||
if( excluded == CSYNC_NOT_EXCLUDED ) {
|
||||
/* Even if it is not excluded by a pattern, maybe it is to be ignored
|
||||
* because it's a hidden file that should not be synced.
|
||||
* This code should probably be in csync_exclude, but it does not have the fs parameter.
|
||||
* Keep it here for now */
|
||||
if (ctx->ignore_hidden_files && (fs->flags & CSYNC_VIO_FILE_FLAGS_HIDDEN)) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file excluded because it is a hidden file: %s", path);
|
||||
excluded = CSYNC_FILE_EXCLUDE_HIDDEN;
|
||||
}
|
||||
} else {
|
||||
/* File is ignored because it's matched by a user- or system exclude pattern. */
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", path, excluded);
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) {
|
||||
return 1;
|
||||
}
|
||||
if (excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncBlackListHook) {
|
||||
|
@ -208,9 +206,9 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||
st->child_modified = 0;
|
||||
st->has_ignored_files = 0;
|
||||
|
||||
/* check hardlink count */
|
||||
/* FIXME: Under which conditions are the following two ifs true and the code
|
||||
* is executed? */
|
||||
if (type == CSYNC_FTW_TYPE_FILE ) {
|
||||
|
||||
if (fs->mtime == 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - mtime is zero!", path);
|
||||
|
||||
|
@ -242,12 +240,14 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (excluded > CSYNC_NOT_EXCLUDED || type == CSYNC_FTW_TYPE_SLINK) {
|
||||
if( type == CSYNC_FTW_TYPE_SLINK ) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK; /* Symbolic links are ignored. */
|
||||
}
|
||||
st->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
goto out;
|
||||
if (ctx->current_fs) {
|
||||
ctx->current_fs->has_ignored_files = true;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Update detection: Check if a database entry exists.
|
||||
|
@ -268,10 +268,10 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||
/* we have an update! */
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Database entry found, compare: %" PRId64 " <-> %" PRId64
|
||||
", etag: %s <-> %s, inode: %" PRId64 " <-> %" PRId64
|
||||
", size: %" PRId64 " <-> %" PRId64 ", perms: %s <-> %s",
|
||||
", size: %" PRId64 " <-> %" PRId64 ", perms: %s <-> %s, ignore: %d",
|
||||
((int64_t) fs->mtime), ((int64_t) tmp->modtime),
|
||||
fs->etag, tmp->etag, (uint64_t) fs->inode, (uint64_t) tmp->inode,
|
||||
(uint64_t) fs->size, (uint64_t) tmp->size, fs->remotePerm, tmp->remotePerm );
|
||||
(uint64_t) fs->size, (uint64_t) tmp->size, fs->remotePerm, tmp->remotePerm, tmp->has_ignored_files );
|
||||
if( !fs->etag) {
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
||||
goto out;
|
||||
|
@ -316,6 +316,12 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
|||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Need to update metadata for: %s", path);
|
||||
st->should_update_metadata = true;
|
||||
}
|
||||
/* If it was remembered in the db that the remote dir has ignored files, store
|
||||
* that so that the reconciler can make advantage of.
|
||||
*/
|
||||
if( ctx->current == REMOTE_REPLICA ) {
|
||||
st->has_ignored_files = tmp->has_ignored_files;
|
||||
}
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
} else {
|
||||
enum csync_vio_file_type_e tmp_vio_type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
||||
|
@ -418,13 +424,19 @@ out:
|
|||
|
||||
/* Set the ignored error string. */
|
||||
if (st->instruction == CSYNC_INSTRUCTION_IGNORE) {
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_LIST) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST; /* File listed on ignore list. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_INVALID_CHAR) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS; /* File contains invalid characters. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_LONG_FILENAME) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME; /* File name is too long. */
|
||||
}
|
||||
if( type == CSYNC_FTW_TYPE_SLINK ) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK; /* Symbolic links are ignored. */
|
||||
} else {
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_LIST) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST; /* File listed on ignore list. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_INVALID_CHAR) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS; /* File contains invalid characters. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_LONG_FILENAME) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME; /* File name is too long. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_HIDDEN ) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_HIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (st->instruction != CSYNC_INSTRUCTION_NONE && st->instruction != CSYNC_INSTRUCTION_IGNORE
|
||||
&& type != CSYNC_FTW_TYPE_DIR) {
|
||||
|
|
|
@ -224,7 +224,12 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
|||
buf->type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
break;
|
||||
} while (0);
|
||||
/* TODO Do we want to parse for CSYNC_VIO_FILE_FLAGS_HIDDEN ? */
|
||||
|
||||
/* Check for the hidden flag */
|
||||
if( fileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) {
|
||||
buf->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
|
||||
}
|
||||
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;
|
||||
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ struct CmdOptions {
|
|||
bool trustSSL;
|
||||
bool useNetrc;
|
||||
bool interactive;
|
||||
bool ignoreHiddenFiles;
|
||||
QString exclude;
|
||||
QString unsyncedfolders;
|
||||
};
|
||||
|
@ -154,6 +155,7 @@ void help()
|
|||
std::cout << " --password, -p [pass] Use [pass] as password" << std::endl;
|
||||
std::cout << " -n Use netrc (5) for login" << std::endl;
|
||||
std::cout << " --non-interactive Do not block execution with interaction" << std::endl;
|
||||
std::cout << " -h Sync hidden files,do not ignore them" << std::endl;
|
||||
std::cout << " --version, -v Display version and exit" << std::endl;
|
||||
std::cout << "" << std::endl;
|
||||
exit(1);
|
||||
|
@ -216,6 +218,8 @@ void parseOptions( const QStringList& app_args, CmdOptions *options )
|
|||
options->trustSSL = true;
|
||||
} else if( option == "-n") {
|
||||
options->useNetrc = true;
|
||||
} else if( option == "-h") {
|
||||
options->ignoreHiddenFiles = false;
|
||||
} else if( option == "--non-interactive") {
|
||||
options->interactive = false;
|
||||
} else if( (option == "-u" || option == "--user") && !it.peekNext().startsWith("-") ) {
|
||||
|
@ -269,6 +273,7 @@ int main(int argc, char **argv) {
|
|||
options.trustSSL = false;
|
||||
options.useNetrc = false;
|
||||
options.interactive = true;
|
||||
options.ignoreHiddenFiles = true;
|
||||
ClientProxy clientProxy;
|
||||
|
||||
parseOptions( app.arguments(), &options );
|
||||
|
@ -364,6 +369,9 @@ restart_sync:
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// ignore hidden files or not
|
||||
_csync_ctx->ignore_hidden_files = options.ignoreHiddenFiles;
|
||||
|
||||
csync_set_module_property(_csync_ctx, "csync_context", _csync_ctx);
|
||||
if( !options.proxy.isNull() ) {
|
||||
QString host;
|
||||
|
|
|
@ -192,6 +192,17 @@ void AccountSettings::slotFolderWizardAccepted()
|
|||
definition.alias = folderWizard->field(QLatin1String("alias")).toString();
|
||||
definition.localPath = folderWizard->field(QLatin1String("sourceFolder")).toString();
|
||||
definition.targetPath = folderWizard->property("targetPath").toString();
|
||||
|
||||
bool ignoreHidden = true;
|
||||
/* take the value from the definition of already existing folders. All folders have
|
||||
* the same setting so far, that's why it's ok to check the first one.
|
||||
* The default is to not sync hidden files
|
||||
*/
|
||||
if( folderMan->map().count() > 0) {
|
||||
ignoreHidden = folderMan->map().first()->ignoreHiddenFiles();
|
||||
}
|
||||
definition.ignoreHiddenFiles = ignoreHidden;
|
||||
|
||||
auto selectiveSyncBlackList = folderWizard->property("selectiveSyncBlackList").toStringList();
|
||||
|
||||
folderMan->setSyncEnabled(true);
|
||||
|
|
|
@ -191,6 +191,17 @@ QString Folder::path() const
|
|||
return p;
|
||||
}
|
||||
|
||||
bool Folder::ignoreHiddenFiles()
|
||||
{
|
||||
bool re(_definition.ignoreHiddenFiles);
|
||||
return re;
|
||||
}
|
||||
|
||||
void Folder::setIgnoreHiddenFiles(bool ignore)
|
||||
{
|
||||
_definition.ignoreHiddenFiles = ignore;
|
||||
}
|
||||
|
||||
QString Folder::cleanPath()
|
||||
{
|
||||
QString cleanedPath = QDir::cleanPath(_definition.localPath);
|
||||
|
@ -813,6 +824,9 @@ void Folder::startSync(const QStringList &pathList)
|
|||
return;
|
||||
}
|
||||
|
||||
// pass the setting if hidden files are to be ignored, will be read in csync_update
|
||||
_csync_ctx->ignore_hidden_files = _definition.ignoreHiddenFiles;
|
||||
|
||||
_engine.reset(new SyncEngine( _accountState->account(), _csync_ctx, path(), remoteUrl().path(), remotePath(), &_journal));
|
||||
|
||||
qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
|
||||
|
@ -1086,6 +1100,7 @@ void FolderDefinition::save(QSettings& settings, const FolderDefinition& folder)
|
|||
settings.setValue(QLatin1String("localPath"), folder.localPath);
|
||||
settings.setValue(QLatin1String("targetPath"), folder.targetPath);
|
||||
settings.setValue(QLatin1String("paused"), folder.paused);
|
||||
settings.setValue(QLatin1String("ignoreHiddenFiles"), folder.ignoreHiddenFiles);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
|
@ -1097,6 +1112,7 @@ bool FolderDefinition::load(QSettings& settings, const QString& alias,
|
|||
folder->localPath = settings.value(QLatin1String("localPath")).toString();
|
||||
folder->targetPath = settings.value(QLatin1String("targetPath")).toString();
|
||||
folder->paused = settings.value(QLatin1String("paused")).toBool();
|
||||
folder->ignoreHiddenFiles = settings.value(QLatin1String("ignoreHiddenFiles"), QVariant(true)).toBool();
|
||||
settings.endGroup();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ public:
|
|||
QString targetPath;
|
||||
/// whether the folder is paused
|
||||
bool paused;
|
||||
/// whether the folder syncs hidden files
|
||||
bool ignoreHiddenFiles;
|
||||
|
||||
/// Saves the folder definition, creating a new settings group.
|
||||
static void save(QSettings& settings, const FolderDefinition& folder);
|
||||
|
@ -168,6 +170,13 @@ public:
|
|||
|
||||
void setDirtyNetworkLimits();
|
||||
|
||||
/**
|
||||
* Ignore syncing of hidden files or not. This is defined in the
|
||||
* folder definition
|
||||
*/
|
||||
bool ignoreHiddenFiles();
|
||||
void setIgnoreHiddenFiles(bool ignore);
|
||||
|
||||
// Used by the Socket API
|
||||
SyncJournalDb *journalDb() { return &_journal; }
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ void FolderMan::registerFolderMonitor( Folder *folder )
|
|||
ConfigFile cfg;
|
||||
fw->addIgnoreListFile( cfg.excludeFile(ConfigFile::SystemScope) );
|
||||
fw->addIgnoreListFile( cfg.excludeFile(ConfigFile::UserScope) );
|
||||
fw->setIgnoreHidden( folder->ignoreHiddenFiles() );
|
||||
|
||||
// Connect the pathChanged signal, which comes with the changed path,
|
||||
// to the signal mapper which maps to the folder alias. The changed path
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
namespace OCC {
|
||||
|
||||
FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
|
||||
: QObject(parent)
|
||||
: QObject(parent),
|
||||
_ignoreHidden(true)
|
||||
{
|
||||
_d.reset(new FolderWatcherPrivate(this, root));
|
||||
|
||||
|
@ -46,6 +47,16 @@ FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
|
|||
FolderWatcher::~FolderWatcher()
|
||||
{ }
|
||||
|
||||
void FolderWatcher::setIgnoreHidden(bool ignore)
|
||||
{
|
||||
_ignoreHidden = ignore;
|
||||
}
|
||||
|
||||
bool FolderWatcher::ignoreHidden()
|
||||
{
|
||||
return _ignoreHidden;
|
||||
}
|
||||
|
||||
void FolderWatcher::addIgnoreListFile( const QString& file )
|
||||
{
|
||||
if( file.isEmpty() ) return;
|
||||
|
@ -71,10 +82,14 @@ bool FolderWatcher::pathIsIgnored( const QString& path )
|
|||
{
|
||||
if( path.isEmpty() ) return true;
|
||||
|
||||
QFileInfo fInfo(path);
|
||||
if( fInfo.isHidden() ) {
|
||||
qDebug() << "* Discarded as is hidden!" << fInfo.filePath();
|
||||
return true;
|
||||
// if events caused by changes to hidden files should be ignored, a QFileInfo
|
||||
// object will tell us if the file is hidden
|
||||
if( _ignoreHidden ) {
|
||||
QFileInfo fInfo(path);
|
||||
if( fInfo.isHidden() ) {
|
||||
qDebug() << "* Discarded as is hidden!" << fInfo.filePath();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Best use csync_excluded_no_ctx() here somehow!
|
||||
|
|
|
@ -77,6 +77,10 @@ public:
|
|||
/* Check if the path is ignored. */
|
||||
bool pathIsIgnored( const QString& path );
|
||||
|
||||
/* set if the folderwatcher ignores events of hidden files */
|
||||
void setIgnoreHidden(bool ignore);
|
||||
bool ignoreHidden();
|
||||
|
||||
signals:
|
||||
/** Emitted when one of the watched directories or one
|
||||
* of the contained files is changed. */
|
||||
|
@ -98,6 +102,7 @@ private:
|
|||
QStringList _ignores;
|
||||
QTime _timer;
|
||||
QSet<QString> _lastPaths;
|
||||
bool _ignoreHidden;
|
||||
|
||||
friend class FolderWatcherPrivate;
|
||||
};
|
||||
|
|
|
@ -57,6 +57,13 @@ IgnoreListEditor::IgnoreListEditor(QWidget *parent) :
|
|||
|
||||
ui->tableWidget->horizontalHeader()->setResizeMode(patternCol, QHeaderView::Stretch);
|
||||
ui->tableWidget->verticalHeader()->setVisible(false);
|
||||
|
||||
/* value for syncing hidden files */
|
||||
bool ignoreHidden = true;
|
||||
if( FolderMan::instance()->map().count() > 0 ) {
|
||||
ignoreHidden = FolderMan::instance()->map().first()->ignoreHiddenFiles();
|
||||
}
|
||||
ui->ignoreHiddenFilesCheckBox->setChecked( !ignoreHidden );
|
||||
}
|
||||
|
||||
IgnoreListEditor::~IgnoreListEditor()
|
||||
|
@ -64,6 +71,11 @@ IgnoreListEditor::~IgnoreListEditor()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
bool IgnoreListEditor::ignoreHiddenFiles()
|
||||
{
|
||||
return ! ui->ignoreHiddenFilesCheckBox->isChecked();
|
||||
}
|
||||
|
||||
void IgnoreListEditor::slotItemSelectionChanged()
|
||||
{
|
||||
QTableWidgetItem *item = ui->tableWidget->currentItem();
|
||||
|
@ -110,6 +122,17 @@ void IgnoreListEditor::slotUpdateLocalIgnoreList()
|
|||
QMessageBox::warning(this, tr("Could not open file"),
|
||||
tr("Cannot write changes to '%1'.").arg(ignoreFile));
|
||||
}
|
||||
|
||||
/* handle the hidden file checkbox */
|
||||
bool ignoreHiddenFiles = ! ui->ignoreHiddenFilesCheckBox->isChecked();
|
||||
|
||||
/* the ignoreHiddenFiles flag is a folder specific setting, but for now, it is
|
||||
* handled globally. Save it to every folder that is defined.
|
||||
*/
|
||||
foreach (Folder* folder, FolderMan::instance()->map()) {
|
||||
folder->setIgnoreHiddenFiles(ignoreHiddenFiles);
|
||||
folder->saveToSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void IgnoreListEditor::slotAddPattern()
|
||||
|
|
|
@ -36,6 +36,8 @@ public:
|
|||
explicit IgnoreListEditor(QWidget *parent = 0);
|
||||
~IgnoreListEditor();
|
||||
|
||||
bool ignoreHiddenFiles();
|
||||
|
||||
private slots:
|
||||
void slotItemSelectionChanged();
|
||||
void slotRemoveCurrentItem();
|
||||
|
|
|
@ -6,96 +6,121 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>471</width>
|
||||
<height>359</height>
|
||||
<width>438</width>
|
||||
<height>463</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Ignored Files Editor</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="5" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Global Ignore Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="ignoreHiddenFilesCheckBox">
|
||||
<property name="text">
|
||||
<string>Sync hidden files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Files Ingored by Patterns</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="removePushButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="addPushButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="3">
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Pattern</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Allow Deletion</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>213</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="descriptionLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>213</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="addPushButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="removePushButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="descriptionLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="3">
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Pattern</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Allow Deletion</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
|
|
@ -311,6 +311,9 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(QString file,QMap
|
|||
if (!file_stat->etag || strlen(file_stat->etag) == 0) {
|
||||
qDebug() << "WARNING: etag of" << file_stat->name << "is" << file_stat->etag << " This must not happen.";
|
||||
}
|
||||
if( file.startsWith(QChar('.')) ) {
|
||||
file_stat->flags = CSYNC_VIO_FILE_FLAGS_HIDDEN;
|
||||
}
|
||||
//qDebug() << "!!!!" << file_stat << file_stat->name << file_stat->file_id << map.count();
|
||||
_results.append(file_stat);
|
||||
}
|
||||
|
|
|
@ -106,7 +106,8 @@ void FileSystem::setFileHidden(const QString& filename, bool hidden)
|
|||
}
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(filename) Q_UNUSED(hidden)
|
||||
Q_UNUSED(filename);
|
||||
Q_UNUSED(hidden);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -348,8 +348,24 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
|||
if (file->remotePerm && file->remotePerm[0]) {
|
||||
item->_remotePerm = QByteArray(file->remotePerm);
|
||||
}
|
||||
|
||||
item->_should_update_metadata = item->_should_update_metadata || file->should_update_metadata;
|
||||
|
||||
/* The flag "serverHasIgnoredFiles" is true if item in question is a directory
|
||||
* that has children which are ignored in sync, either because the files are
|
||||
* matched by an ignore pattern, or because they are hidden.
|
||||
*
|
||||
* Only the information about the server side ignored files is stored to the
|
||||
* database and thus written to the item here. For the local repository its
|
||||
* generated by the walk through the real file tree by discovery phase.
|
||||
*
|
||||
* It needs to go to the sync journal becasue the stat information about remote
|
||||
* files are often read from database rather than being pulled from remote.
|
||||
*/
|
||||
if( remote ) {
|
||||
item->_serverHasIgnoredFiles = (file->has_ignored_files > 0);
|
||||
}
|
||||
|
||||
// record the seen files to be able to clean the journal later
|
||||
_seenFiles.insert(item->_file);
|
||||
if (!renameTarget.isEmpty()) {
|
||||
|
@ -376,6 +392,9 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
|||
case CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME:
|
||||
item->_errorString = tr("Filename is too long.");
|
||||
break;
|
||||
case CSYNC_STATUS_INDIVIDUAL_EXCLUDE_HIDDEN:
|
||||
item->_errorString = tr("File is ignored because it's hidden.");
|
||||
break;
|
||||
case CYSNC_STATUS_FILE_LOCKED_OR_OPEN:
|
||||
item->_errorString = QLatin1String("File locked"); // don't translate, internal use!
|
||||
break;
|
||||
|
@ -423,7 +442,7 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote )
|
|||
item->_type = SyncFileItem::UnknownType;
|
||||
}
|
||||
|
||||
SyncFileItem::Direction dir;
|
||||
SyncFileItem::Direction dir = SyncFileItem::None;
|
||||
|
||||
int re = 0;
|
||||
switch(file->instruction) {
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
};
|
||||
|
||||
SyncFileItem() : _type(UnknownType), _direction(None), _isDirectory(false),
|
||||
_hasBlacklistEntry(false), _status(NoStatus),
|
||||
_serverHasIgnoredFiles(false), _hasBlacklistEntry(false), _status(NoStatus),
|
||||
_isRestoration(false), _should_update_metadata(false),
|
||||
_httpErrorCode(0), _requestDuration(0), _affectedItems(1),
|
||||
_instruction(CSYNC_INSTRUCTION_NONE), _modtime(0), _size(0), _inode(0)
|
||||
|
@ -130,6 +130,7 @@ public:
|
|||
Type _type BITFIELD(3);
|
||||
Direction _direction BITFIELD(2);
|
||||
bool _isDirectory BITFIELD(1);
|
||||
bool _serverHasIgnoredFiles BITFIELD(1);
|
||||
|
||||
/// Whether there's an entry in the blacklist table.
|
||||
/// Note: that entry may have retries left, so this can be true
|
||||
|
|
|
@ -346,13 +346,13 @@ bool SyncJournalDb::checkConnect()
|
|||
}
|
||||
|
||||
_getFileRecordQuery.reset(new SqlQuery(_db));
|
||||
_getFileRecordQuery->prepare("SELECT path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize FROM "
|
||||
_getFileRecordQuery->prepare("SELECT path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote FROM "
|
||||
"metadata WHERE phash=?1" );
|
||||
|
||||
_setFileRecordQuery.reset(new SqlQuery(_db) );
|
||||
_setFileRecordQuery->prepare("INSERT OR REPLACE INTO metadata "
|
||||
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize) "
|
||||
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13);" );
|
||||
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote) "
|
||||
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14);" );
|
||||
|
||||
_getDownloadInfoQuery.reset(new SqlQuery(_db) );
|
||||
_getDownloadInfoQuery->prepare( "SELECT tmpfile, etag, errorcount FROM "
|
||||
|
@ -516,6 +516,16 @@ bool SyncJournalDb::updateMetadataTableStructure()
|
|||
commitInternal("update database structure: add pathlen index");
|
||||
|
||||
}
|
||||
|
||||
if( columns.indexOf(QLatin1String("ignoredChildrenRemote")) == -1 ) {
|
||||
SqlQuery query(_db);
|
||||
query.prepare("ALTER TABLE metadata ADD COLUMN ignoredChildrenRemote INT;");
|
||||
if( !query.exec()) {
|
||||
sqlFail("updateMetadataTableStructure: add ignoredChildrenRemote column", query);
|
||||
re = false;
|
||||
}
|
||||
commitInternal("update database structure: add ignoredChildrenRemote col");
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
|
@ -630,6 +640,7 @@ bool SyncJournalDb::setFileRecord( const SyncJournalFileRecord& _record )
|
|||
_setFileRecordQuery->bindValue(11, fileId );
|
||||
_setFileRecordQuery->bindValue(12, remotePerm );
|
||||
_setFileRecordQuery->bindValue(13, record._fileSize );
|
||||
_setFileRecordQuery->bindValue(14, record._serverHasIgnoredFiles ? 1:0);
|
||||
|
||||
if( !_setFileRecordQuery->exec() ) {
|
||||
qWarning() << "Error SQL statement setFileRecord: " << _setFileRecordQuery->lastQuery() << " :"
|
||||
|
@ -640,7 +651,7 @@ bool SyncJournalDb::setFileRecord( const SyncJournalFileRecord& _record )
|
|||
qDebug() << _setFileRecordQuery->lastQuery() << phash << plen << record._path << record._inode
|
||||
<< record._mode
|
||||
<< QString::number(Utility::qDateTimeToTime_t(record._modtime)) << QString::number(record._type)
|
||||
<< record._etag << record._fileId << record._remotePerm << record._fileSize;
|
||||
<< record._etag << record._fileId << record._remotePerm << record._fileSize << (record._serverHasIgnoredFiles ? 1:0);
|
||||
|
||||
_setFileRecordQuery->reset();
|
||||
return true;
|
||||
|
@ -719,6 +730,7 @@ SyncJournalFileRecord SyncJournalDb::getFileRecord( const QString& filename )
|
|||
rec._fileId = _getFileRecordQuery->baValue(8);
|
||||
rec._remotePerm = _getFileRecordQuery->baValue(9);
|
||||
rec._fileSize = _getFileRecordQuery->int64Value(10);
|
||||
rec._serverHasIgnoredFiles = (_getFileRecordQuery->intValue(11) > 0);
|
||||
} else {
|
||||
QString err = _getFileRecordQuery->error();
|
||||
qDebug() << "No journal entry found for " << filename;
|
||||
|
|
|
@ -28,14 +28,14 @@
|
|||
namespace OCC {
|
||||
|
||||
SyncJournalFileRecord::SyncJournalFileRecord()
|
||||
:_inode(0), _type(0), _fileSize(0), _mode(0)
|
||||
:_inode(0), _type(0), _fileSize(0), _mode(0), _serverHasIgnoredFiles(false)
|
||||
{
|
||||
}
|
||||
|
||||
SyncJournalFileRecord::SyncJournalFileRecord(const SyncFileItem &item, const QString &localFileName)
|
||||
: _path(item._file), _modtime(Utility::qDateTimeFromTime_t(item._modtime)),
|
||||
_type(item._type), _etag(item._etag), _fileId(item._fileId), _fileSize(item._size),
|
||||
_remotePerm(item._remotePerm), _mode(0)
|
||||
_remotePerm(item._remotePerm), _mode(0), _serverHasIgnoredFiles(item._serverHasIgnoredFiles)
|
||||
{
|
||||
// use the "old" inode coming with the item for the case where the
|
||||
// filesystem stat fails. That can happen if the the file was removed
|
||||
|
|
|
@ -37,15 +37,16 @@ public:
|
|||
return !_path.isEmpty();
|
||||
}
|
||||
|
||||
QString _path;
|
||||
quint64 _inode;
|
||||
QDateTime _modtime;
|
||||
int _type;
|
||||
QString _path;
|
||||
quint64 _inode;
|
||||
QDateTime _modtime;
|
||||
int _type;
|
||||
QByteArray _etag;
|
||||
QByteArray _fileId;
|
||||
qint64 _fileSize;
|
||||
QByteArray _remotePerm;
|
||||
int _mode;
|
||||
int _mode;
|
||||
bool _serverHasIgnoredFiles;
|
||||
};
|
||||
|
||||
bool OWNCLOUDSYNC_EXPORT
|
||||
|
|
Loading…
Reference in a new issue