Comparar commits
132 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| a139d1a279 | |||
| 13e624c38f | |||
| 276985f6c3 | |||
| 49f8143f00 | |||
| bea7241910 | |||
| 61b4da944c | |||
| 6fe1868693 | |||
| 9641c7a1e7 | |||
| 3e59a9b316 | |||
| 4998303c42 | |||
| ceef2f2d46 | |||
| 8b18600d7e | |||
| 6cc63462b3 | |||
| a1dc4069c9 | |||
| 86846af59d | |||
| 5bfa02602d | |||
| 9be23984eb | |||
| eb8de8e3c0 | |||
| ec7333a4bf | |||
| e485c5c008 | |||
| 6451eb3ade | |||
| 01528427b5 | |||
| cec4d7b9ff | |||
| efa7821dd2 | |||
| 89f55cf9df | |||
| 52552a4204 | |||
| 2f3db04e87 | |||
| 2d6e473a40 | |||
| 92027e8692 | |||
| 2723cd225e | |||
| acd151102c | |||
| 77e790d2ee | |||
| 899c675f0a | |||
| fb76487e76 | |||
| 0c0a3ca0a5 | |||
| 5377d1e283 | |||
| 676ad530e7 | |||
| fbcb01ed27 | |||
| c2b006e857 | |||
| 0e7ccea588 | |||
| c16deb3e44 | |||
| 019544fcfd | |||
| 5f0167b19e | |||
| 29d3c33eb2 | |||
| 469eca1f5f | |||
| 0864d67a9a | |||
| e9503664f5 | |||
| 58cee61624 | |||
| d23d07f99b | |||
| d70db810dd | |||
| 842129f99d | |||
| 36d61ef3a9 | |||
| f1f27221a7 | |||
| eb012d26ee | |||
| 9ee8187083 | |||
| b0c45cfc89 | |||
| 90cea69692 | |||
| 155bdfbffe | |||
| 0e2782d369 | |||
| 6b3d0e69aa | |||
| f30aee6d4e | |||
| 82f86eb019 | |||
| 9573c5e64d | |||
| 15f2b911d9 | |||
| f5aff70398 | |||
| e3a4c3989a | |||
| 3e954bc17f | |||
| 2527569bb8 | |||
| 1e197531cb | |||
| 8b876576eb | |||
| a2287c9657 | |||
| 34c59ba9ed | |||
| c8014a0afd | |||
| 456d82715e | |||
| 8ca3eb7883 | |||
| c110745330 | |||
| 19521863a0 | |||
| c256896165 | |||
| ef922f60fa | |||
| 733ea90e6b | |||
| a4e1fa9dcf | |||
| 1a1684ca2a | |||
| 9c8572e335 | |||
| e675a34fbb | |||
| db24f60ae3 | |||
| 9e2d3f5bc7 | |||
| e6be670e49 | |||
| 46ce2f4722 | |||
| 166a0f60ca | |||
| a9019ccbad | |||
| 0a4806af44 | |||
| e33b89c222 | |||
| 273590fdfc | |||
| 0960058842 | |||
| 16e28567a6 | |||
| 3bef42db6b | |||
| 27d23edacc | |||
| e1a48e3c33 | |||
| 5d13f9290f | |||
| c84140d293 | |||
| 838c072ccc | |||
| ed6a708460 | |||
| 0c9dcdafc2 | |||
| da26e59770 | |||
| 3c24d5a148 | |||
| c222793525 | |||
| 28018e8590 | |||
| 4c79ce2ae6 | |||
| 7c75a39bc1 | |||
| f0dc3b2deb | |||
| 84ede3f01f | |||
| 2daf895e43 | |||
| 3b651b2da9 | |||
| 6fd930908c | |||
| 62125a442d | |||
| 2d54fb2ff9 | |||
| e46fad52bb | |||
| c41f6ed76b | |||
| 818b5854ce | |||
| 79abb8b4e3 | |||
| fad387b6b8 | |||
| a1558100b8 | |||
| 4f3f642da6 | |||
| f3cfd2b70b | |||
| 78caa1a712 | |||
| 0884ad6517 | |||
| 37fc4e4332 | |||
| 9cc90159f1 | |||
| 4ceee86c66 | |||
| b9ea7c3414 | |||
| 3033e693be | |||
| a1bc01d3b1 |
+1
-1
@@ -27,7 +27,7 @@ https://github.com/owncloud/client.
|
||||
|
||||
## Building the source code
|
||||
|
||||
[Building the Client](http://doc.owncloud.org/desktop/2.0/building.html)
|
||||
[Building the Client](http://doc.owncloud.org/desktop/2.2/building.html)
|
||||
in the ownCloud Desktop Client manual.
|
||||
|
||||
## Maintainers and Contributors
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
#
|
||||
# ownCloud is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# ownCLoud is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
||||
@@ -9,6 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "No instal·lar"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ja instal·lat"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Trieu la manera com voleu instal·lar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Una versió més recent de ${APPLICATION_NAME} ja està instal.lada!! No es recomana instal.lar una versió més antiga. Si realment voleu instal.lar una versió més antiga, és millor primer desinstal.lar la versió actual. Seleccioni l'operació que desitjeu realitzar i feu clic a Següent per a continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} ja està instal·lat.$\n$\nSeleccioneu la operació que voleu fer i feu clic a Següent per continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Afegir/Reinstal.lar components"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstal.lar ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstal.lar ${APPLICATION_NAME}"
|
||||
@@ -37,7 +38,6 @@ StrCpy $UAC_ERROR_ELEVATE "No es pot elevar, error:"
|
||||
StrCpy $UAC_INSTALLER_REQUIRE_ADMIN "Aquest instal·lador requereix accés d'administrador, intenteu-ho de nou"
|
||||
StrCpy $INIT_INSTALLER_RUNNING "L'instal·lador ja s'està executant."
|
||||
StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Aquest desinstal·lador requereix accés d'administrador, intenteu-ho de nou."
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "El servei de inici de sessió no s'està executant, s'està abortant!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "El desinstal·lador ja s'està executant."
|
||||
StrCpy $SectionGroup_Shortcuts "Dreceres"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Logon service is not running, aborting!"
|
||||
|
||||
@@ -32,7 +32,7 @@ find_library(CMOCKA_LIBRARY
|
||||
NAMES
|
||||
cmocka
|
||||
PATHS
|
||||
${CMOCKA_ROOT_DIR}/include
|
||||
${CMOCKA_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
if (CMOCKA_LIBRARY)
|
||||
|
||||
+10
-22
@@ -89,7 +89,7 @@ static int _data_cmp(const void *key, const void *data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
void csync_create(CSYNC **csync, const char *local) {
|
||||
CSYNC *ctx;
|
||||
size_t len = 0;
|
||||
|
||||
@@ -103,12 +103,6 @@ void csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
|
||||
ctx->local.uri = c_strndup(local, len);
|
||||
|
||||
/* remove trailing slashes */
|
||||
len = strlen(remote);
|
||||
while(len > 0 && remote[len - 1] == '/') --len;
|
||||
|
||||
ctx->remote.uri = c_strndup(remote, len);
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
ctx->current_fs = NULL;
|
||||
@@ -120,7 +114,7 @@ void csync_create(CSYNC **csync, const char *local, const char *remote) {
|
||||
*csync = ctx;
|
||||
}
|
||||
|
||||
void csync_init(CSYNC *ctx) {
|
||||
void csync_init(CSYNC *ctx, const char *db_file) {
|
||||
assert(ctx);
|
||||
/* Do not initialize twice */
|
||||
|
||||
@@ -131,6 +125,9 @@ void csync_init(CSYNC *ctx) {
|
||||
|
||||
ctx->remote.type = REMOTE_REPLICA;
|
||||
|
||||
SAFE_FREE(ctx->statedb.file);
|
||||
ctx->statedb.file = c_strdup(db_file);
|
||||
|
||||
c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp);
|
||||
c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp);
|
||||
|
||||
@@ -152,19 +149,11 @@ int csync_update(CSYNC *ctx) {
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
/* create/load statedb */
|
||||
rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db",
|
||||
ctx->local.uri);
|
||||
if (rc < 0) {
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
return rc;
|
||||
}
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Journal: %s", ctx->statedb.file);
|
||||
|
||||
if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
|
||||
/* Path of database file is set in csync_init */
|
||||
if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
@@ -199,7 +188,7 @@ int csync_update(CSYNC *ctx) {
|
||||
ctx->current = REMOTE_REPLICA;
|
||||
ctx->replica = ctx->remote.type;
|
||||
|
||||
rc = csync_ftw(ctx, ctx->remote.uri, csync_walker, MAX_DEPTH);
|
||||
rc = csync_ftw(ctx, "", csync_walker, MAX_DEPTH);
|
||||
if (rc < 0) {
|
||||
if(ctx->status_code == CSYNC_STATUS_OK) {
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||
@@ -521,7 +510,6 @@ static void _csync_clean_ctx(CSYNC *ctx)
|
||||
c_rbtree_free(ctx->local.tree);
|
||||
c_rbtree_free(ctx->remote.tree);
|
||||
|
||||
SAFE_FREE(ctx->statedb.file);
|
||||
SAFE_FREE(ctx->remote.root_perms);
|
||||
}
|
||||
|
||||
@@ -578,8 +566,8 @@ int csync_destroy(CSYNC *ctx) {
|
||||
|
||||
_csync_clean_ctx(ctx);
|
||||
|
||||
SAFE_FREE(ctx->statedb.file);
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
SAFE_FREE(ctx->remote.uri);
|
||||
SAFE_FREE(ctx->error_string);
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
|
||||
+2
-2
@@ -317,7 +317,7 @@ typedef const char* (*csync_checksum_hook) (
|
||||
*
|
||||
* @param csync The context variable to allocate.
|
||||
*/
|
||||
void OCSYNC_EXPORT csync_create(CSYNC **csync, const char *local, const char *remote);
|
||||
void OCSYNC_EXPORT csync_create(CSYNC **csync, const char *local);
|
||||
|
||||
/**
|
||||
* @brief Initialize the file synchronizer.
|
||||
@@ -326,7 +326,7 @@ void OCSYNC_EXPORT csync_create(CSYNC **csync, const char *local, const char *re
|
||||
*
|
||||
* @param ctx The context to initialize.
|
||||
*/
|
||||
void OCSYNC_EXPORT csync_init(CSYNC *ctx);
|
||||
void OCSYNC_EXPORT csync_init(CSYNC *ctx, const char *db_file);
|
||||
|
||||
/**
|
||||
* @brief Update detection
|
||||
|
||||
@@ -230,6 +230,11 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(c_strlist_t *excludes, const ch
|
||||
}
|
||||
blen = strlen(bname);
|
||||
|
||||
rc = csync_fnmatch("._sync_*.db*", bname, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
goto out;
|
||||
}
|
||||
rc = csync_fnmatch(".csync_journal.db*", bname, 0);
|
||||
if (rc == 0) {
|
||||
match = CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
|
||||
@@ -126,7 +126,6 @@ struct csync_s {
|
||||
} local;
|
||||
|
||||
struct {
|
||||
char *uri;
|
||||
c_rbtree_t *tree;
|
||||
enum csync_replica_e type;
|
||||
int read_from_db;
|
||||
|
||||
@@ -65,7 +65,21 @@ static c_rbnode_t *_csync_check_ignored(c_rbtree_t *tree, const char *path, int
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* The main function in the reconcile pass.
|
||||
*
|
||||
* It's called for each entry in the local and remote rbtrees by
|
||||
* csync_reconcile()
|
||||
*
|
||||
* Before the reconcile phase the trees already know about changes
|
||||
* relative to the sync journal. This function's job is to spot conflicts
|
||||
* between local and remote changes and adjust the nodes accordingly.
|
||||
*
|
||||
* See doc/dev/sync-algorithm.md for an overview.
|
||||
*
|
||||
*
|
||||
* Older detail comment:
|
||||
*
|
||||
* We merge replicas at the file level. The merged replica contains the
|
||||
* superset of files that are on the local machine and server copies of
|
||||
* the replica. In the case where the same file is in both the local
|
||||
|
||||
+24
-95
@@ -56,26 +56,13 @@ static uint64_t _hash_of_file(CSYNC *ctx, const char *file) {
|
||||
|
||||
if( ctx && file ) {
|
||||
path = file;
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
if (strlen(path) <= strlen(ctx->local.uri)) {
|
||||
return 0;
|
||||
}
|
||||
path += strlen(ctx->local.uri) + 1;
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
if (strlen(path) <= strlen(ctx->remote.uri)) {
|
||||
return 0;
|
||||
}
|
||||
path += strlen(ctx->remote.uri) + 1;
|
||||
break;
|
||||
default:
|
||||
path = NULL;
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
len = strlen(path);
|
||||
|
||||
h = c_jhash64((uint8_t *) path, len, 0);
|
||||
}
|
||||
return h;
|
||||
@@ -158,7 +145,19 @@ static bool _csync_mtime_equal(time_t a, time_t b)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The main function of the discovery/update pass.
|
||||
*
|
||||
* It's called (indirectly) by csync_update(), once for each entity in the
|
||||
* local filesystem and once for each entity in the server data.
|
||||
*
|
||||
* It has two main jobs:
|
||||
* - figure out whether anything happened compared to the sync journal
|
||||
* and set (primarily) the instruction flag accordingly
|
||||
* - build the ctx->local.tree / ctx->remote.tree
|
||||
*
|
||||
* See doc/dev/sync-algorithm.md for an overview.
|
||||
*/
|
||||
static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
const csync_vio_file_stat_t *fs, const int type) {
|
||||
uint64_t h = 0;
|
||||
@@ -176,25 +175,12 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
}
|
||||
|
||||
path = file;
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
if (strlen(path) <= strlen(ctx->local.uri)) {
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
path += strlen(ctx->local.uri) + 1;
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
if (strlen(path) <= strlen(ctx->remote.uri)) {
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
path += strlen(ctx->remote.uri) + 1;
|
||||
break;
|
||||
default:
|
||||
path = NULL;
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = strlen(path);
|
||||
@@ -617,16 +603,7 @@ int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs,
|
||||
|
||||
static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
|
||||
{
|
||||
const char *path = NULL;
|
||||
|
||||
if( strlen(uri) < strlen(ctx->remote.uri)+1) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "name does not contain remote uri!");
|
||||
return false;
|
||||
}
|
||||
|
||||
path = uri + strlen(ctx->remote.uri)+1;
|
||||
|
||||
if( csync_statedb_get_below_path(ctx, path) < 0 ) {
|
||||
if( csync_statedb_get_below_path(ctx, uri) < 0 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "StateDB could not be read!");
|
||||
return false;
|
||||
}
|
||||
@@ -668,12 +645,6 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
|
||||
bool do_read_from_db = (ctx->current == REMOTE_REPLICA && ctx->remote.read_from_db);
|
||||
|
||||
if (uri[0] == '\0') {
|
||||
errno = ENOENT;
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
read_from_db = ctx->remote.read_from_db;
|
||||
|
||||
// if the etag of this dir is still the same, its content is restored from the
|
||||
@@ -687,16 +658,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
goto done;
|
||||
}
|
||||
|
||||
const char *uri_for_vio = uri;
|
||||
if (ctx->current == REMOTE_REPLICA) {
|
||||
uri_for_vio += strlen(ctx->remote.uri);
|
||||
if (strlen(uri_for_vio) > 0 && uri_for_vio[0] == '/') {
|
||||
uri_for_vio++; // cut leading slash
|
||||
}
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "URI without fuzz for %s is \"%s\"", uri, uri_for_vio);
|
||||
}
|
||||
|
||||
if ((dh = csync_vio_opendir(ctx, uri_for_vio)) == NULL) {
|
||||
if ((dh = csync_vio_opendir(ctx, uri)) == NULL) {
|
||||
if (ctx->abort) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Aborted!");
|
||||
ctx->status_code = CSYNC_STATUS_ABORTED;
|
||||
@@ -742,8 +704,6 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
}
|
||||
|
||||
while ((dirent = csync_vio_readdir(ctx, dh))) {
|
||||
const char *path = NULL;
|
||||
size_t ulen = 0;
|
||||
int flen;
|
||||
int flag;
|
||||
|
||||
@@ -769,50 +729,19 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
continue;
|
||||
}
|
||||
|
||||
flen = asprintf(&filename, "%s/%s", uri, d_name);
|
||||
if (flen < 0) {
|
||||
if (uri[0] == '\0') {
|
||||
filename = c_strdup(d_name);
|
||||
flen = strlen(d_name);
|
||||
} else {
|
||||
flen = asprintf(&filename, "%s/%s", uri, d_name);
|
||||
}
|
||||
if (flen < 0 || !filename) {
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Create relative path */
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
ulen = strlen(ctx->local.uri) + 1;
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
ulen = strlen(ctx->remote.uri) + 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (((size_t)flen) < ulen) {
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
path = filename + ulen;
|
||||
|
||||
/* skip ".csync_journal.db" and ".csync_journal.db.ctmp" */
|
||||
/* Isn't this done via csync_exclude already? */
|
||||
if (c_streq(path, ".csync_journal.db")
|
||||
|| c_streq(path, ".csync_journal.db.ctmp")
|
||||
|| c_streq(path, ".csync_journal.db.ctmp-journal")
|
||||
|| c_streq(path, ".csync-progressdatabase")
|
||||
|| c_streq(path, ".csync_journal.db-shm")
|
||||
|| c_streq(path, ".csync_journal.db-wal")
|
||||
|| c_streq(path, ".csync_journal.db-journal")) {
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
SAFE_FREE(filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Only for the local replica we have to stat(), for the remote one we have all data already */
|
||||
if (ctx->replica == LOCAL_REPLICA) {
|
||||
res = csync_vio_stat(ctx, filename, dirent);
|
||||
|
||||
@@ -23,38 +23,36 @@
|
||||
|
||||
#include "csync_private.h"
|
||||
|
||||
static void setup(void **state) {
|
||||
static int setup(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_module(void **state) {
|
||||
static int setup_module(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
|
||||
csync_init(csync);
|
||||
csync_init(csync, "foo");
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
@@ -66,10 +64,9 @@ static void teardown(void **state) {
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_csync_commit(void **state)
|
||||
@@ -97,10 +94,10 @@ static void check_csync_commit_dummy(void **state)
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(check_csync_commit, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_commit_dummy, setup_module, teardown),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_commit, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_commit_dummy, setup_module, teardown),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ static void check_csync_create(void **state)
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
|
||||
csync_create(&csync, "/tmp/csync1");
|
||||
|
||||
rc = csync_destroy(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
@@ -50,11 +50,11 @@ static void check_csync_create(void **state)
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test(check_csync_destroy_null),
|
||||
unit_test(check_csync_create),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(check_csync_destroy_null),
|
||||
cmocka_unit_test(check_csync_create),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,19 +29,20 @@
|
||||
|
||||
#define EXCLUDE_LIST_FILE SOURCEDIR"/../sync-exclude.lst"
|
||||
|
||||
static void setup(void **state) {
|
||||
static int setup(void **state) {
|
||||
CSYNC *csync;
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_init(void **state) {
|
||||
static int setup_init(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes));
|
||||
assert_int_equal(rc, 0);
|
||||
@@ -59,9 +60,10 @@ static void setup_init(void **state) {
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
@@ -74,6 +76,8 @@ static void teardown(void **state) {
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_csync_exclude_add(void **state)
|
||||
@@ -143,6 +147,17 @@ static void check_csync_excluded(void **state)
|
||||
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "subdir/.csync_journal.db", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
|
||||
|
||||
/* also the new form of the database name */
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "._sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "._sync_5bdd60bdfcfa.db.ctmp", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "._sync_5bdd60bdfcfa.db-shm", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "subdir/._sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE);
|
||||
assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
|
||||
|
||||
|
||||
/* pattern ]*.directory - ignore and remove */
|
||||
rc = csync_excluded_no_ctx(csync->excludes, "my.~directory", CSYNC_FTW_TYPE_FILE);
|
||||
@@ -380,16 +395,16 @@ static void check_csync_exclude_expand_escapes(void **state)
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(check_csync_exclude_add, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_exclude_load, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_excluded, setup_init, teardown),
|
||||
unit_test_setup_teardown(check_csync_excluded_traversal, setup_init, teardown),
|
||||
unit_test_setup_teardown(check_csync_pathes, setup_init, teardown),
|
||||
unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown),
|
||||
unit_test_setup_teardown(check_csync_excluded_performance, setup_init, teardown),
|
||||
unit_test(check_csync_exclude_expand_escapes),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_exclude_add, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_exclude_load, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_excluded, setup_init, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_excluded_traversal, setup_init, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_pathes, setup_init, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_excluded_performance, setup_init, teardown),
|
||||
cmocka_unit_test(check_csync_exclude_expand_escapes),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -23,37 +23,33 @@
|
||||
|
||||
#include "csync_private.h"
|
||||
|
||||
static void setup(void **state) {
|
||||
static int setup(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_module(void **state) {
|
||||
static int setup_module(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "dummy://foo/bar");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
@@ -65,28 +61,28 @@ static void teardown(void **state) {
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_csync_init(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
|
||||
csync_init(csync);
|
||||
csync_init(csync, "");
|
||||
|
||||
assert_int_equal(csync->status & CSYNC_STATUS_INIT, 1);
|
||||
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(check_csync_init, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_init, setup_module, teardown),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_init, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_init, setup_module, teardown),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,22 +26,21 @@
|
||||
#include "csync_log.c"
|
||||
#include "c_private.h"
|
||||
|
||||
static void setup(void **state) {
|
||||
static int setup(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
@@ -53,10 +52,9 @@ static void teardown(void **state) {
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_log_callback(int verbosity,
|
||||
@@ -140,11 +138,11 @@ static void check_logging(void **state)
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test(check_set_log_level),
|
||||
unit_test(check_set_auth_callback),
|
||||
unit_test_setup_teardown(check_logging, setup, teardown),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(check_set_log_level),
|
||||
cmocka_unit_test(check_set_auth_callback),
|
||||
cmocka_unit_test_setup_teardown(check_logging, setup, teardown),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -48,10 +48,10 @@ static void check_csync_normalize_etag(void **state)
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test(check_csync_normalize_etag),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(check_csync_normalize_etag),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#define TESTDB "/tmp/check_csync1/test.db"
|
||||
|
||||
static void setup(void **state) {
|
||||
static int setup(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
@@ -36,7 +36,7 @@ static void setup(void **state) {
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
csync->statedb.file = c_strdup( TESTDB );
|
||||
*state = csync;
|
||||
@@ -47,9 +47,11 @@ static void setup(void **state) {
|
||||
|
||||
rc = sqlite3_close(db);
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
@@ -60,6 +62,8 @@ static void teardown(void **state) {
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_csync_statedb_load(void **state)
|
||||
@@ -116,11 +120,11 @@ static void check_csync_statedb_close(void **state)
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(check_csync_statedb_load, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_statedb_close, setup, teardown),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_load, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_close, setup, teardown),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,23 +27,19 @@
|
||||
|
||||
|
||||
|
||||
static void setup(void **state)
|
||||
static int setup(void **state)
|
||||
{
|
||||
CSYNC *csync;
|
||||
int rc = 0;
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_init(csync);
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
csync_init(csync, TESTDB);
|
||||
|
||||
sqlite3 *db = NULL;
|
||||
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||
@@ -55,9 +51,11 @@ static void setup(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_db(void **state)
|
||||
static int setup_db(void **state)
|
||||
{
|
||||
char *errmsg;
|
||||
int rc = 0;
|
||||
@@ -93,10 +91,12 @@ static void setup_db(void **state)
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc = 0;
|
||||
|
||||
@@ -106,10 +106,10 @@ static void teardown(void **state) {
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -210,15 +210,15 @@ static void check_csync_statedb_get_stat_by_inode_not_found(void **state)
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(check_csync_statedb_query_statement, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_statedb_drop_tables, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_statedb_insert_metadata, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_statedb_write, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_statedb_get_stat_by_hash_not_found, setup_db, teardown),
|
||||
unit_test_setup_teardown(check_csync_statedb_get_stat_by_inode_not_found, setup_db, teardown),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_query_statement, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_drop_tables, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_insert_metadata, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_write, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_hash_not_found, setup_db, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_inode_not_found, setup_db, teardown),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ static void statedb_insert_metadata(sqlite3 *db)
|
||||
}
|
||||
}
|
||||
|
||||
static void setup(void **state)
|
||||
static int setup(void **state)
|
||||
{
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
@@ -91,10 +91,8 @@ static void setup(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1", "/tmp/check_csync2");
|
||||
csync_init(csync);
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
csync_init(csync, TESTDB);
|
||||
|
||||
/* Create a new db with metadata */
|
||||
sqlite3 *db;
|
||||
@@ -111,9 +109,11 @@ static void setup(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup_ftw(void **state)
|
||||
static int setup_ftw(void **state)
|
||||
{
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
@@ -122,10 +122,8 @@ static void setup_ftw(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp", "/tmp");
|
||||
csync_init(csync);
|
||||
csync_create(&csync, "/tmp");
|
||||
csync_init(csync, TESTDB);
|
||||
|
||||
sqlite3 *db = NULL;
|
||||
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||
@@ -139,9 +137,11 @@ static void setup_ftw(void **state)
|
||||
|
||||
csync->statedb.file = c_strdup( TESTDB );
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void teardown(void **state)
|
||||
static int teardown(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
@@ -151,9 +151,11 @@ static void teardown(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void teardown_rm(void **state) {
|
||||
static int teardown_rm(void **state) {
|
||||
int rc;
|
||||
|
||||
teardown(state);
|
||||
@@ -162,8 +164,8 @@ static void teardown_rm(void **state) {
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync2");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create a file stat, caller must free memory */
|
||||
@@ -430,19 +432,19 @@ static void check_csync_ftw_failing_fn(void **state)
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test_setup_teardown(check_csync_detect_update, setup, teardown_rm),
|
||||
unit_test_setup_teardown(check_csync_detect_update_db_none, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_detect_update_db_eval, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_detect_update_db_rename, setup, teardown),
|
||||
unit_test_setup_teardown(check_csync_detect_update_db_new, setup, teardown_rm),
|
||||
unit_test_setup_teardown(check_csync_detect_update_null, setup, teardown_rm),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update, setup, teardown_rm),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_none, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_eval, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_rename, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_new, setup, teardown_rm),
|
||||
cmocka_unit_test_setup_teardown(check_csync_detect_update_null, setup, teardown_rm),
|
||||
|
||||
unit_test_setup_teardown(check_csync_ftw, setup_ftw, teardown_rm),
|
||||
unit_test_setup_teardown(check_csync_ftw_empty_uri, setup_ftw, teardown_rm),
|
||||
unit_test_setup_teardown(check_csync_ftw_failing_fn, setup_ftw, teardown_rm),
|
||||
cmocka_unit_test_setup_teardown(check_csync_ftw, setup_ftw, teardown_rm),
|
||||
cmocka_unit_test_setup_teardown(check_csync_ftw_empty_uri, setup_ftw, teardown_rm),
|
||||
cmocka_unit_test_setup_teardown(check_csync_ftw_failing_fn, setup_ftw, teardown_rm),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,11 +43,11 @@ static void check_csync_memstat(void **state)
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test(check_csync_instruction_str),
|
||||
unit_test(check_csync_memstat),
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(check_csync_instruction_str),
|
||||
cmocka_unit_test(check_csync_memstat),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -457,6 +457,7 @@ sub traverse( $$;$ )
|
||||
|
||||
$isHere = 1 if( $acceptConflicts && !$isHere && $f =~ /_conflict/ );
|
||||
$isHere = 1 if( $f =~ /\.csync/ );
|
||||
$isHere = 1 if( $f =~ /\._sync_/ );
|
||||
assert( $isHere, "Filename local, but not remote: $f" );
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ assertLocalAndRemoteDir( 'remoteToLocal1', 1);
|
||||
|
||||
printInfo("simulate a owncloud 5 update by removing all the fileid");
|
||||
## simulate a owncloud 5 update by removing all the fileid
|
||||
system( "sqlite3 " . localDir() . ".csync_journal.db \"UPDATE metadata SET fileid='';\"");
|
||||
system( "sqlite3 " . localDir() . "._sync_*.db \"UPDATE metadata SET fileid='';\"");
|
||||
#refresh the ids
|
||||
csync();
|
||||
assertLocalAndRemoteDir( 'remoteToLocal1', 1);
|
||||
|
||||
@@ -61,7 +61,7 @@ sub getETagFromJournal($$)
|
||||
{
|
||||
my ($name,$num) = @_;
|
||||
|
||||
my $sql = "sqlite3 " . localDir() . ".csync_journal.db \"SELECT md5 FROM metadata WHERE path='$name';\"";
|
||||
my $sql = "sqlite3 " . localDir() . "._sync_*.db \"SELECT md5 FROM metadata WHERE path='$name';\"";
|
||||
open(my $fh, '-|', $sql) or die $!;
|
||||
my $etag = <$fh>;
|
||||
close $fh;
|
||||
|
||||
@@ -37,8 +37,8 @@ sub assertCsyncJournalOk {
|
||||
my $path = $_[0];
|
||||
|
||||
# FIXME: should test also remoteperm but it's not working with owncloud6
|
||||
# my $cmd = 'sqlite3 ' . $path . '.csync_journal.db "SELECT count(*) from metadata where length(remotePerm) == 0 or length(fileId) == 0"';
|
||||
my $cmd = 'sqlite3 ' . $path . '.csync_journal.db "SELECT count(*) from metadata where length(fileId) == 0"';
|
||||
# my $cmd = 'sqlite3 ' . $path . '._sync_*.db "SELECT count(*) from metadata where length(remotePerm) == 0 or length(fileId) == 0"';
|
||||
my $cmd = 'sqlite3 ' . $path . '._sync_*.db "SELECT count(*) from metadata where length(fileId) == 0"';
|
||||
my $result = `$cmd`;
|
||||
assert($result == "0");
|
||||
}
|
||||
@@ -170,14 +170,14 @@ assertLocalAndRemoteDir( '', 0);
|
||||
|
||||
#######################################################################
|
||||
printInfo( "move a directory in a outside read only folder" );
|
||||
system("sqlite3 " . localDir().'.csync_journal.db .dump');
|
||||
system("sqlite3 " . localDir().'._sync_*.db .dump');
|
||||
|
||||
#Missing directory should be restored
|
||||
#new directory should be uploaded
|
||||
system("mv " . localDir().'readonlyDirectory_PERM_M_/subdir_PERM_CK_ ' . localDir().'normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_' );
|
||||
|
||||
csync();
|
||||
system("sqlite3 " . localDir().'.csync_journal.db .dump');
|
||||
system("sqlite3 " . localDir().'._sync_*.db .dump');
|
||||
assertCsyncJournalOk(localDir());
|
||||
|
||||
# old name restored
|
||||
@@ -229,7 +229,38 @@ system("rm -r " . localDir(). "readonlyDirectory_PERM_M_/moved_PERM_CK_");
|
||||
|
||||
assertLocalAndRemoteDir( '', 0);
|
||||
|
||||
system("sqlite3 " . localDir().'.csync_journal.db .dump');
|
||||
system("sqlite3 " . localDir().'._sync_*.db .dump');
|
||||
|
||||
|
||||
#######################################################################
|
||||
printInfo( "multiple restores of a file create different conflict files" );
|
||||
|
||||
system("sleep 1"); #make sure changes have different mtime
|
||||
|
||||
system("echo 'modified_1' > ". localDir() . "readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN_.data");
|
||||
|
||||
#do the sync
|
||||
csync();
|
||||
assertCsyncJournalOk(localDir());
|
||||
|
||||
system("sleep 1"); #make sure changes have different mtime
|
||||
|
||||
system("echo 'modified_2' > ". localDir() . "readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN_.data");
|
||||
|
||||
#do the sync
|
||||
csync();
|
||||
assertCsyncJournalOk(localDir());
|
||||
|
||||
# there should be two conflict files
|
||||
# TODO check that the conflict file has the right content
|
||||
my @conflicts = glob(localDir().'readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN__conflict-*.data' );
|
||||
assert( scalar @conflicts == 2 );
|
||||
# remove the conflicts for the next assertLocalAndRemoteDir
|
||||
system("rm " . localDir().'readonlyDirectory_PERM_M_/canotBeModified_PERM_DVN__conflict-*.data' );
|
||||
|
||||
### Both side should still be the same
|
||||
assertLocalAndRemoteDir( '', 0);
|
||||
|
||||
|
||||
|
||||
cleanup();
|
||||
|
||||
@@ -48,7 +48,7 @@ static void setup(void **state)
|
||||
rc = system("rm -rf /tmp/csync_test");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/csync1", "/tmp/csync2");
|
||||
csync_create(&csync, "/tmp/csync1");
|
||||
|
||||
csync->replica = LOCAL_REPLICA;
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ static void setup_testenv(void **state) {
|
||||
statevar *mystate = malloc( sizeof(statevar) );
|
||||
mystate->result = NULL;
|
||||
|
||||
csync_create(&(mystate->csync), "/tmp/csync1", "/tmp/csync2");
|
||||
csync_create(&(mystate->csync), "/tmp/csync1");
|
||||
|
||||
mystate->csync->replica = LOCAL_REPLICA;
|
||||
|
||||
|
||||
@@ -153,7 +153,8 @@ By default, the ownCloud Client ignores the following files:
|
||||
|
||||
* Files matched by one of the patterns defined in the Ignored Files Editor
|
||||
* Files containing characters that do not work on certain file systems ``(`\, /, :, ?, *, ", >, <, |`)``.
|
||||
* Files starting with ``.csync_journal.db``, as these files are reserved for journalling.
|
||||
* Files starting with ``._sync_xxxxxxx.db`` and the old format ``.csync_journal.db``,
|
||||
as these files are reserved for journalling.
|
||||
|
||||
If a pattern selected using a checkbox in the `ignoredFilesEditor-label` (or if
|
||||
a line in the exclude file starts with the character ``]`` directly followed by
|
||||
|
||||
+16
-2
@@ -66,11 +66,18 @@ recipes.
|
||||
|
||||
To set up your build environment for development using HomeBrew_:
|
||||
|
||||
1. Add the ownCloud repository using the following command::
|
||||
1. Install Xcode
|
||||
2. Install Xcode command line tools::
|
||||
xcode-select --install
|
||||
|
||||
3. Install homebrew::
|
||||
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
|
||||
4. Add the ownCloud repository using the following command::
|
||||
|
||||
brew tap owncloud/owncloud
|
||||
|
||||
2. Install any missing dependencies::
|
||||
5. Install any missing dependencies::
|
||||
|
||||
brew install $(brew deps owncloud-client)
|
||||
|
||||
@@ -80,6 +87,9 @@ To set up your build environment for development using HomeBrew_:
|
||||
|
||||
Where ``x.z`` is the current version of Qt 5 that brew has installed
|
||||
on your machine.
|
||||
4. Install qtkeychain from here: git clone https://github.com/frankosterfeld/qtkeychain.git
|
||||
make sure you make the same install prefix as later while building the client e.g. -
|
||||
``DCMAKE_INSTALL_PREFIX=/Path/to/client-install``
|
||||
|
||||
5. For compilation of the client, follow the :ref:`generic-build-instructions`.
|
||||
|
||||
@@ -234,6 +244,10 @@ To build the most up-to-date version of the client:
|
||||
.. note:: On Mac OS X, you need to specify ``-DCMAKE_INSTALL_PREFIX=target``,
|
||||
where ``target`` is a private location, i.e. in parallel to your build
|
||||
dir by specifying ``../install``.
|
||||
|
||||
..note:: qtkeychain must be compiled with the same prefix e.g CMAKE_INSTALL_PREFIX=/Users/path/to/client/install/
|
||||
|
||||
.. note:: Example:: cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ -D_OPENSSL_LIBDIR=/usr/local/opt/openssl/lib/ -D_OPENSSL_INCLUDEDIR=/usr/local/opt/openssl/include/ -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include/ -DNO_SHIBBOLETH=1
|
||||
|
||||
4. Call ``make``.
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
Sync Algorithm
|
||||
==============
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
This is a technical description of the synchronization (sync) algorithm used by the ownCloud client.
|
||||
|
||||
The sync algorithm is the thing that looks at the local and remote file system trees and the sync journal and decides which steps need to be taken to bring the two trees into synchronization. It's different from the propagator, whose job it is to actually execute these steps.
|
||||
|
||||
|
||||
Definitions
|
||||
-----------
|
||||
|
||||
- local tree: The files and directories on the local file system that shall be kept in sync with the remote tree.
|
||||
- remote tree: The files and directories on the ownCloud server that shall be kept in sync with the local tree.
|
||||
- sync journal (journal): A snapshot of file and directory metadata that the sync algorithm uses as a baseline to detect local or remote changes. Typically stored in a database.
|
||||
- file and directory metadata:
|
||||
- mtimes
|
||||
- sizes
|
||||
- inodes (journal and local only): Representation of filesystem object. Useful for rename detection.
|
||||
- etags (journal and remote only): The server assigns a new etag when a file or directory changes.
|
||||
- checksums (journal and remote only): Checksum algorithm applied to a file's contents.
|
||||
- permissions (journal and remote only)
|
||||
|
||||
|
||||
Phases
|
||||
------
|
||||
|
||||
### Discovery (aka Update)
|
||||
|
||||
The discovery phase collects file and directory metadata from the local and remote trees, detecting differences between each tree and the journal.
|
||||
|
||||
Afterwards, we have two trees that tell us what happened relative to the journal. But there may still be conflicts if something happened to an entity both locally and on the remote.
|
||||
|
||||
- Input: file system, server data, journal
|
||||
- Output: two c_rbtree_t*, representing the local and remote trees
|
||||
|
||||
- Note on remote discovery: Since a change to a file on the server causes the etags of all parent folders to change, folders with an unchanged etag can be read from the journal directly and don't need to be walked into.
|
||||
|
||||
- Details
|
||||
- csync_update() uses csync_ftw() on the local and remote trees, one after the other.
|
||||
- csync_ftw() iterates through the entities in a tree and calls csync_walker() for each.
|
||||
- csync_walker() calls _csync_detect_update() on each.
|
||||
- _csync_detect_update() compares the item to its journal entry (if any) to detect new, changed or renamed files. This is the main function of this pass.
|
||||
|
||||
|
||||
|
||||
### Reconcile
|
||||
|
||||
The reconcile phase compares and adjusts the local and remote trees (in both directions), detecting conflicts.
|
||||
|
||||
Afterwards, there are still two trees, but conflicts are marked in them.
|
||||
|
||||
- Input: c_rbtree_t* for the local and remote trees, journal (for some rename-related queries)
|
||||
- Output: changes c_rbtree_t* in-place
|
||||
|
||||
- Details
|
||||
- csync_reconcile() runs csync_reconcile_updates() for the local and remote trees, one after the other.
|
||||
- csync_reconcile_updates() uses c_rbtree_walk() to iterate through the entries, calling _csync_merge_algorithm_visitor() for each.
|
||||
- _csync_merge_algorithm_visitor() checks whether the other tree also has an entry for that node and merges the actions, detecting conflicts. This is the main function of this pass.
|
||||
|
||||
|
||||
### Post-Reconcile
|
||||
|
||||
The post-reconcile phase merges the two trees into one set of SyncFileItems.
|
||||
|
||||
Afterwards, there is a list of items that can tell the propagator what needs to be done.
|
||||
|
||||
- Input: c_rbtree_t* for the local and remote trees
|
||||
- Output: QMap<QString, SyncFileItemPtr>
|
||||
|
||||
- Note that some "propagations", specifically cheap metadata-only updates, are already done at this stage.
|
||||
|
||||
- Details
|
||||
- csync_walk_local_tree() and csync_walk_remote_tree() are called.
|
||||
- They use _csync_walk_tree() to run SyncEngine::treewalkFile() on each entry.
|
||||
- treewalkFile() creates and fills SyncFileItems for each entry, ensuring that each file only has a single instance. This is the main function of this pass.
|
||||
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
An overview of the propagation steps is still missing. The sync protocol is documented at https://github.com/cernbox/smashbox/blob/master/protocol/protocol.md.
|
||||
@@ -12,7 +12,7 @@ Desktop Sync client enables you to:
|
||||
Your files are always automatically synchronized between your ownCloud server
|
||||
and local PC.
|
||||
|
||||
Because of various technical issues, desktop sync clients older than 1.7 will
|
||||
Because of various technical issues, desktop sync clients older than 2.2.1 will
|
||||
not allowed to connect and sync with the ownCloud 8.1+ server. It is highly
|
||||
recommended to keep your client updated.
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
+101
-4
@@ -415,6 +415,102 @@ X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
|
||||
GenericName[oc]=Dorsièr de Sincronizacion
|
||||
@@ -505,10 +601,10 @@ Comment[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
|
||||
GenericName[cs_CZ]=Synchronizace adresáře
|
||||
Name[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
|
||||
Icon[cs_CZ]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
|
||||
GenericName[ru]=Синхронизация папки
|
||||
Name[ru]=Настольный клиент синхронизации @НАЗВАНИЕ_ПРИЛОЖЕНИЯ@
|
||||
Icon[ru]=@ВЫПОЛНЯЕМОЕ_ПРИЛОЖЕНИЕ@
|
||||
Comment[ru]=Настольный клиент синхронизации @APPLICATION_NAME@
|
||||
GenericName[ru]=Синхронизация каталогов
|
||||
Name[ru]=Настольный клиент синхронизации @APPLICATION_NAME@
|
||||
Icon[ru]=@APPLICATION_EXECUTABLE@
|
||||
Comment[sl]=@APPLICATION_NAME@ ‒ Program za usklajevanje datotek z namizjem
|
||||
GenericName[sl]=Usklajevanje map
|
||||
Name[sl]=@APPLICATION_NAME@ ‒ Program za usklajevanje datotek z namizjem
|
||||
@@ -550,6 +646,7 @@ Comment[th_TH]=@APPLICATION_NAME@ ไคลเอนต์ประสานข
|
||||
GenericName[th_TH]=ประสานข้อมูลโฟลเดอร์
|
||||
Name[th_TH]= @APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
|
||||
Icon[th_TH]=@APPLICATION_EXECUTABLE@
|
||||
GenericName[es_MX]=Sincronización de Carpetas
|
||||
Comment[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
|
||||
GenericName[nb_NO]=Mappesynkronisering
|
||||
Name[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import os
|
||||
import urllib
|
||||
import socket
|
||||
import tempfile
|
||||
|
||||
from gi.repository import GObject, Nautilus
|
||||
|
||||
@@ -43,7 +44,7 @@ def get_runtime_dir():
|
||||
try:
|
||||
return os.environ['XDG_RUNTIME_DIR']
|
||||
except KeyError:
|
||||
fallback = '/tmp/runtime-' + os.environ['USER']
|
||||
fallback = os.path.join(tempfile.gettempdir(), 'runtime-' + os.environ['USER'])
|
||||
return fallback
|
||||
|
||||
|
||||
@@ -86,22 +87,17 @@ class SocketConnect(GObject.GObject):
|
||||
def _connectToSocketServer(self):
|
||||
try:
|
||||
self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
postfix = "/" + appname + "/socket" # Should use os.path.join instead
|
||||
sock_file = get_runtime_dir() + postfix
|
||||
print ("Socket: " + sock_file + " <=> " + postfix)
|
||||
if sock_file != postfix:
|
||||
try:
|
||||
print("Socket File: " + sock_file)
|
||||
self._sock.connect(sock_file)
|
||||
self.connected = True
|
||||
print("Setting connected to %r." % self.connected )
|
||||
self._watch_id = GObject.io_add_watch(self._sock, GObject.IO_IN, self._handle_notify)
|
||||
print("Socket watch id: " + str(self._watch_id))
|
||||
return False # Don't run again
|
||||
except Exception as e:
|
||||
print("Could not connect to unix socket. " + str(e))
|
||||
else:
|
||||
print("Sock-File not valid: " + sock_file)
|
||||
sock_file = os.path.join(get_runtime_dir(), appname, "socket")
|
||||
try:
|
||||
print("Socket File: " + sock_file)
|
||||
self._sock.connect(sock_file) # fails if sock_file doesn't exist
|
||||
self.connected = True
|
||||
print("Setting connected to %r." % self.connected )
|
||||
self._watch_id = GObject.io_add_watch(self._sock, GObject.IO_IN, self._handle_notify)
|
||||
print("Socket watch id: " + str(self._watch_id))
|
||||
return False # Don't run again
|
||||
except Exception as e:
|
||||
print("Could not connect to unix socket. " + str(e))
|
||||
except Exception as e: # Bad habbit
|
||||
print("Connect could not be established, try again later.")
|
||||
self._sock.close()
|
||||
@@ -157,32 +153,65 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
|
||||
def __init__(self):
|
||||
GObject.GObject.__init__(self)
|
||||
|
||||
def check_registered_paths(self, filename):
|
||||
topLevelFolder = False
|
||||
internalFile = False
|
||||
for reg_path in socketConnect.registered_paths:
|
||||
if filename == reg_path:
|
||||
topLevelFolder = True
|
||||
break
|
||||
if filename.startswith(reg_path):
|
||||
internalFile = True
|
||||
# you can't have a registered path below another so it is save to break here
|
||||
break
|
||||
return (topLevelFolder, internalFile)
|
||||
|
||||
def get_file_items(self, window, files):
|
||||
# Show the menu extension to share a file or folder
|
||||
#
|
||||
# Show if file is OK.
|
||||
# Ignore top level folders.
|
||||
# Also show extension for folders
|
||||
# if there is a OK or SYNC underneath.
|
||||
# This is only
|
||||
|
||||
if len(files) != 1:
|
||||
return
|
||||
file = files[0]
|
||||
items = []
|
||||
|
||||
# Internal or external file?!
|
||||
syncedFile = False
|
||||
for reg_path in socketConnect.registered_paths:
|
||||
topLevelFolder = False
|
||||
filename = get_local_path(file.get_uri())
|
||||
# Check if its a folder (ends with an /), if yes add a "/"
|
||||
# otherwise it will not find the entry in the table
|
||||
if os.path.isdir(filename + "/"):
|
||||
filename += "/"
|
||||
# Check if toplevel folder, we need to ignore those as they cannot be shared
|
||||
if filename == reg_path:
|
||||
topLevelFolder=True
|
||||
# Only show the menu extension if the file is synced and the sync
|
||||
# status is ok. Not for ignored files etc.
|
||||
# ignore top level folders
|
||||
if filename.startswith(reg_path) and topLevelFolder == False and socketConnect.nautilusVFSFile_table[filename]['state'].startswith('OK'):
|
||||
syncedFile = True
|
||||
filename = get_local_path(file.get_uri())
|
||||
# Check if its a folder (ends with an /), if yes add a "/"
|
||||
# otherwise it will not find the entry in the table
|
||||
isDir = os.path.isdir(filename + os.sep)
|
||||
if isDir:
|
||||
filename += os.sep
|
||||
|
||||
# If it is neither in a synced folder or is a directory
|
||||
if not syncedFile:
|
||||
# Check if toplevel folder, we need to ignore those as they cannot be shared
|
||||
topLevelFolder, internalFile = self.check_registered_paths(filename)
|
||||
if topLevelFolder or not internalFile:
|
||||
return items
|
||||
|
||||
entry = socketConnect.nautilusVFSFile_table.get(filename)
|
||||
if not entry:
|
||||
return items
|
||||
|
||||
shareable = False
|
||||
state = entry['state']
|
||||
state_ok = state.startswith('OK')
|
||||
state_sync = state.startswith('SYNC')
|
||||
if state_ok:
|
||||
shareable = True
|
||||
elif state_sync and isDir:
|
||||
# some file below is OK or SYNC
|
||||
for key, value in socketConnect.nautilusVFSFile_table.items():
|
||||
if key != filename and key.startswith(filename):
|
||||
state = value['state']
|
||||
if state.startswith('OK') or state.startswith('SYNC'):
|
||||
shareable = True
|
||||
break
|
||||
|
||||
if not shareable:
|
||||
return items
|
||||
|
||||
# Create a menu item
|
||||
@@ -303,7 +332,7 @@ class SyncStateExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.Info
|
||||
|
||||
filename = get_local_path(item.get_uri())
|
||||
if item.is_directory():
|
||||
filename += '/'
|
||||
filename += os.sep
|
||||
|
||||
inScope = False
|
||||
for reg_path in socketConnect.registered_paths:
|
||||
|
||||
+15
-11
@@ -58,7 +58,6 @@ struct CmdOptions {
|
||||
QString password;
|
||||
QString proxy;
|
||||
bool silent;
|
||||
bool bundleRequests;
|
||||
bool trustSSL;
|
||||
bool useNetrc;
|
||||
bool interactive;
|
||||
@@ -158,7 +157,6 @@ void help()
|
||||
std::cout << std::endl;
|
||||
std::cout << "Options:" << std::endl;
|
||||
std::cout << " --silent, -s Don't be so verbose" << std::endl;
|
||||
std::cout << " --bundle-requests, -b Bundle Requests if supported" << std::endl;
|
||||
std::cout << " --httpproxy [proxy] Specify a http proxy to use." << std::endl;
|
||||
std::cout << " Proxy is http://server:port" << std::endl;
|
||||
std::cout << " --trust Trust the SSL certification." << std::endl;
|
||||
@@ -226,8 +224,6 @@ void parseOptions( const QStringList& app_args, CmdOptions *options )
|
||||
options->silent = true;
|
||||
} else if( option == "--trust") {
|
||||
options->trustSSL = true;
|
||||
} else if( option == "-b" || option == "--bundle-requests") {
|
||||
options->bundleRequests = true;
|
||||
} else if( option == "-n") {
|
||||
options->useNetrc = true;
|
||||
} else if( option == "-h") {
|
||||
@@ -282,7 +278,6 @@ void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QStringList &newList)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
@@ -296,7 +291,6 @@ int main(int argc, char **argv) {
|
||||
|
||||
CmdOptions options;
|
||||
options.silent = false;
|
||||
options.bundleRequests = false;
|
||||
options.trustSSL = false;
|
||||
options.useNetrc = false;
|
||||
options.interactive = true;
|
||||
@@ -388,11 +382,20 @@ int main(int argc, char **argv) {
|
||||
QByteArray remUrl = options.target_url.toUtf8();
|
||||
|
||||
// Find the folder and the original owncloud url
|
||||
QStringList splitted = url.path().split(account->davPath());
|
||||
QStringList splitted = url.path().split("/" + account->davPath());
|
||||
url.setPath(splitted.value(0));
|
||||
|
||||
url.setScheme(url.scheme().replace("owncloud", "http"));
|
||||
QString folder = splitted.value(1);
|
||||
|
||||
QUrl credentialFreeUrl = url;
|
||||
credentialFreeUrl.setUserName(QString());
|
||||
credentialFreeUrl.setPassword(QString());
|
||||
|
||||
// Remote folders typically start with a / and don't end with one
|
||||
QString folder = "/" + splitted.value(1);
|
||||
if (folder.endsWith("/") && folder != "/") {
|
||||
folder.chop(1);
|
||||
}
|
||||
|
||||
SimpleSslErrorHandler *sslErrorHandler = new SimpleSslErrorHandler;
|
||||
|
||||
@@ -421,7 +424,6 @@ int main(int argc, char **argv) {
|
||||
|
||||
loop.exec();
|
||||
#endif
|
||||
account->setBundleRequestsIfCapable(options.bundleRequests);
|
||||
|
||||
// much lower age than the default since this utility is usually made to be run right after a change in the tests
|
||||
SyncEngine::minimumFileAgeForUpload = 0;
|
||||
@@ -476,12 +478,14 @@ restart_sync:
|
||||
}
|
||||
|
||||
Cmd cmd;
|
||||
SyncJournalDb db(options.source_dir);
|
||||
QString dbPath = options.source_dir + SyncJournalDb::makeDbName(credentialFreeUrl, folder, user);
|
||||
SyncJournalDb db(dbPath);
|
||||
|
||||
if (!selectiveSyncList.empty()) {
|
||||
selectiveSyncFixup(&db, selectiveSyncList);
|
||||
}
|
||||
|
||||
SyncEngine engine(account, options.source_dir, QUrl(options.target_url), folder, &db);
|
||||
SyncEngine engine(account, options.source_dir, folder, &db);
|
||||
engine.setIgnoreHiddenFiles(options.ignoreHiddenFiles);
|
||||
QObject::connect(&engine, SIGNAL(finished(bool)), &app, SLOT(quit()));
|
||||
QObject::connect(&engine, SIGNAL(transmissionProgress(ProgressInfo)), &cmd, SLOT(transmissionProgressSlot()));
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -199,6 +199,9 @@ IF( WIN32 )
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.rc
|
||||
@ONLY)
|
||||
set(client_version ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
IF(NOT MSVC)
|
||||
set(client_manifest ${CMAKE_CURRENT_SOURCE_DIR}/manifest-mingw.rc)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
set( final_src
|
||||
@@ -206,6 +209,7 @@ set( final_src
|
||||
${client_SRCS}
|
||||
${client_UI_SRCS}
|
||||
${client_version}
|
||||
${client_manifest}
|
||||
${guiMoc}
|
||||
${client_I18N}
|
||||
${3rdparty_SRC}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
@@ -288,7 +289,8 @@ void AccountSettings::slotFolderWizardAccepted()
|
||||
FolderDefinition definition;
|
||||
definition.localPath = FolderDefinition::prepareLocalPath(
|
||||
folderWizard->field(QLatin1String("sourceFolder")).toString());
|
||||
definition.targetPath = folderWizard->property("targetPath").toString();
|
||||
definition.targetPath = FolderDefinition::prepareTargetPath(
|
||||
folderWizard->property("targetPath").toString());
|
||||
|
||||
{
|
||||
QDir dir(definition.localPath);
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
@@ -616,7 +617,7 @@ void ActivitySettings::slotCopyToClipboard()
|
||||
message = tr("The sync activity list has been copied to the clipboard.");
|
||||
} else if(idx == 2 ) {
|
||||
// issues Widget
|
||||
message = tr("The list of unsynched items has been copied to the clipboard.");
|
||||
message = tr("The list of unsynced items has been copied to the clipboard.");
|
||||
_protocolWidget->storeSyncIssues(ts);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
+72
-7
@@ -46,6 +46,7 @@
|
||||
|
||||
namespace OCC {
|
||||
|
||||
const char oldJournalPath[] = ".csync_journal.db";
|
||||
|
||||
Folder::Folder(const FolderDefinition& definition,
|
||||
AccountState* accountState,
|
||||
@@ -60,8 +61,9 @@ Folder::Folder(const FolderDefinition& definition,
|
||||
, _lastSyncDuration(0)
|
||||
, _consecutiveFailingSyncs(0)
|
||||
, _consecutiveFollowUpSyncs(0)
|
||||
, _journal(definition.localPath)
|
||||
, _journal(_definition.absoluteJournalPath())
|
||||
, _fileLog(new SyncRunFileLog)
|
||||
, _saveBackwardsCompatible(false)
|
||||
{
|
||||
qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
|
||||
qRegisterMetaType<SyncFileItem::Direction>("SyncFileItem::Direction");
|
||||
@@ -81,7 +83,7 @@ Folder::Folder(const FolderDefinition& definition,
|
||||
|
||||
_syncResult.setFolder(_definition.alias);
|
||||
|
||||
_engine.reset(new SyncEngine(_accountState->account(), path(), remoteUrl(), remotePath(), &_journal));
|
||||
_engine.reset(new SyncEngine(_accountState->account(), path(), remotePath(), &_journal));
|
||||
// pass the setting if hidden files are to be ignored, will be read in csync_update
|
||||
_engine->setIgnoreHiddenFiles(_definition.ignoreHiddenFiles);
|
||||
|
||||
@@ -124,6 +126,7 @@ Folder::~Folder()
|
||||
_engine.reset();
|
||||
}
|
||||
|
||||
|
||||
void Folder::checkLocalPath()
|
||||
{
|
||||
const QFileInfo fi(_definition.localPath);
|
||||
@@ -203,7 +206,7 @@ void Folder::setIgnoreHiddenFiles(bool ignore)
|
||||
_definition.ignoreHiddenFiles = ignore;
|
||||
}
|
||||
|
||||
QString Folder::cleanPath()
|
||||
QString Folder::cleanPath() const
|
||||
{
|
||||
QString cleanedPath = QDir::cleanPath(_canonicalLocalPath);
|
||||
|
||||
@@ -584,8 +587,33 @@ void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
|
||||
|
||||
void Folder::saveToSettings() const
|
||||
{
|
||||
// Remove first to make sure we don't get duplicates
|
||||
removeFromSettings();
|
||||
|
||||
auto settings = _accountState->settings();
|
||||
settings->beginGroup(QLatin1String("Folders"));
|
||||
|
||||
// The folder is saved to backwards-compatible "Folders"
|
||||
// section only if it has the migrate flag set (i.e. was in
|
||||
// there before) or if the folder is the only one for the
|
||||
// given target path.
|
||||
// This ensures that older clients will not read a configuration
|
||||
// where two folders for different accounts point at the same
|
||||
// local folders.
|
||||
bool oneAccountOnly = true;
|
||||
foreach (Folder* other, FolderMan::instance()->map()) {
|
||||
if (other != this && other->cleanPath() == this->cleanPath()) {
|
||||
oneAccountOnly = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool compatible = _saveBackwardsCompatible || oneAccountOnly;
|
||||
|
||||
if (compatible) {
|
||||
settings->beginGroup(QLatin1String("Folders"));
|
||||
} else {
|
||||
settings->beginGroup(QLatin1String("Multifolders"));
|
||||
}
|
||||
FolderDefinition::save(*settings, _definition);
|
||||
|
||||
settings->sync();
|
||||
@@ -594,9 +622,12 @@ void Folder::saveToSettings() const
|
||||
|
||||
void Folder::removeFromSettings() const
|
||||
{
|
||||
auto settings = _accountState->settings();
|
||||
auto settings = _accountState->settings();
|
||||
settings->beginGroup(QLatin1String("Folders"));
|
||||
settings->remove(FolderMan::escapeAlias(_definition.alias));
|
||||
settings->endGroup();
|
||||
settings->beginGroup(QLatin1String("Multifolders"));
|
||||
settings->remove(FolderMan::escapeAlias(_definition.alias));
|
||||
}
|
||||
|
||||
bool Folder::isFileExcludedAbsolute(const QString& fullPath) const
|
||||
@@ -628,12 +659,12 @@ void Folder::slotTerminateSync()
|
||||
// local folder is synced to the same ownCloud.
|
||||
void Folder::wipe()
|
||||
{
|
||||
QString stateDbFile = path()+QLatin1String(".csync_journal.db");
|
||||
QString stateDbFile = _engine->journal()->databaseFilePath();
|
||||
|
||||
// Delete files that have been partially downloaded.
|
||||
slotDiscardDownloadProgress();
|
||||
|
||||
//Unregister the socket API so it does not keep the .sync_journal file open
|
||||
//Unregister the socket API so it does not keep the ._sync_journal file open
|
||||
FolderMan::instance()->socketApi()->slotUnregisterPath(alias());
|
||||
_journal.close(); // close the sync journal
|
||||
|
||||
@@ -950,6 +981,11 @@ void Folder::scheduleThisFolderSoon()
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::setSaveBackwardsCompatible(bool save)
|
||||
{
|
||||
_saveBackwardsCompatible = save;
|
||||
}
|
||||
|
||||
void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction, bool *cancel)
|
||||
{
|
||||
ConfigFile cfgFile;
|
||||
@@ -1002,6 +1038,7 @@ void FolderDefinition::save(QSettings& settings, const FolderDefinition& folder)
|
||||
{
|
||||
settings.beginGroup(FolderMan::escapeAlias(folder.alias));
|
||||
settings.setValue(QLatin1String("localPath"), folder.localPath);
|
||||
settings.setValue(QLatin1String("journalPath"), folder.journalPath);
|
||||
settings.setValue(QLatin1String("targetPath"), folder.targetPath);
|
||||
settings.setValue(QLatin1String("paused"), folder.paused);
|
||||
settings.setValue(QLatin1String("ignoreHiddenFiles"), folder.ignoreHiddenFiles);
|
||||
@@ -1014,6 +1051,7 @@ bool FolderDefinition::load(QSettings& settings, const QString& alias,
|
||||
settings.beginGroup(alias);
|
||||
folder->alias = FolderMan::unescapeAlias(alias);
|
||||
folder->localPath = settings.value(QLatin1String("localPath")).toString();
|
||||
folder->journalPath = settings.value(QLatin1String("journalPath")).toString();
|
||||
folder->targetPath = settings.value(QLatin1String("targetPath")).toString();
|
||||
folder->paused = settings.value(QLatin1String("paused")).toBool();
|
||||
folder->ignoreHiddenFiles = settings.value(QLatin1String("ignoreHiddenFiles"), QVariant(true)).toBool();
|
||||
@@ -1023,6 +1061,9 @@ bool FolderDefinition::load(QSettings& settings, const QString& alias,
|
||||
// code we assum /, so clean it up now.
|
||||
folder->localPath = prepareLocalPath(folder->localPath);
|
||||
|
||||
// Target paths also have a convention
|
||||
folder->targetPath = prepareTargetPath(folder->targetPath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1035,5 +1076,29 @@ QString FolderDefinition::prepareLocalPath(const QString& path)
|
||||
return p;
|
||||
}
|
||||
|
||||
QString FolderDefinition::prepareTargetPath(const QString &path)
|
||||
{
|
||||
QString p = path;
|
||||
if (p.endsWith(QLatin1Char('/'))) {
|
||||
p.chop(1);
|
||||
}
|
||||
// Doing this second ensures the empty string or "/" come
|
||||
// out as "/".
|
||||
if (!p.startsWith(QLatin1Char('/'))) {
|
||||
p.prepend(QLatin1Char('/'));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
QString FolderDefinition::absoluteJournalPath() const
|
||||
{
|
||||
return QDir(localPath).filePath(journalPath);
|
||||
}
|
||||
|
||||
QString FolderDefinition::defaultJournalPath(AccountPtr account)
|
||||
{
|
||||
return SyncJournalDb::makeDbName(account->url(), targetPath, account->credentials()->user());
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
|
||||
+28
-1
@@ -53,6 +53,8 @@ public:
|
||||
QString alias;
|
||||
/// path on local machine
|
||||
QString localPath;
|
||||
/// path to the journal, usually relative to localPath
|
||||
QString journalPath;
|
||||
/// path on remote
|
||||
QString targetPath;
|
||||
/// whether the folder is paused
|
||||
@@ -69,6 +71,15 @@ public:
|
||||
|
||||
/// Ensure / as separator and trailing /.
|
||||
static QString prepareLocalPath(const QString& path);
|
||||
|
||||
/// Ensure starting / and no ending /.
|
||||
static QString prepareTargetPath(const QString& path);
|
||||
|
||||
/// journalPath relative to localPath.
|
||||
QString absoluteJournalPath() const;
|
||||
|
||||
/// Returns the relative journal path that's appropriate for this folder and account.
|
||||
QString defaultJournalPath(AccountPtr account);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -111,7 +122,7 @@ public:
|
||||
/**
|
||||
* wrapper for QDir::cleanPath("Z:\\"), which returns "Z:\\", but we need "Z:" instead
|
||||
*/
|
||||
QString cleanPath();
|
||||
QString cleanPath() const;
|
||||
|
||||
/**
|
||||
* remote folder path
|
||||
@@ -206,6 +217,12 @@ public:
|
||||
*/
|
||||
void scheduleThisFolderSoon();
|
||||
|
||||
/**
|
||||
* Migration: When this flag is true, this folder will save to
|
||||
* the backwards-compatible 'Folders' section in the config file.
|
||||
*/
|
||||
void setSaveBackwardsCompatible(bool save);
|
||||
|
||||
signals:
|
||||
void syncStateChange();
|
||||
void syncStarted();
|
||||
@@ -334,6 +351,16 @@ private:
|
||||
QScopedPointer<SyncRunFileLog> _fileLog;
|
||||
|
||||
QTimer _scheduleSelfTimer;
|
||||
|
||||
/**
|
||||
* When the same local path is synced to multiple accounts, only one
|
||||
* of them can be stored in the settings in a way that's compatible
|
||||
* with old clients that don't support it. This flag marks folders
|
||||
* that shall be written in a backwards-compatible way, by being set
|
||||
* on the *first* Folder instance that was configured for each local
|
||||
* path.
|
||||
*/
|
||||
bool _saveBackwardsCompatible;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+119
-52
@@ -209,18 +209,16 @@ int FolderMan::setupFolders()
|
||||
continue;
|
||||
}
|
||||
settings->beginGroup(id);
|
||||
|
||||
settings->beginGroup(QLatin1String("Folders"));
|
||||
foreach (const auto& folderAlias, settings->childGroups()) {
|
||||
FolderDefinition folderDefinition;
|
||||
if (FolderDefinition::load(*settings, folderAlias, &folderDefinition)) {
|
||||
Folder* f = addFolderInternal(std::move(folderDefinition), account.data());
|
||||
if (f) {
|
||||
scheduleFolder(f);
|
||||
emit folderSyncStateChange(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
settings->endGroup(); // Folders
|
||||
setupFoldersHelper(*settings, account, true);
|
||||
settings->endGroup();
|
||||
|
||||
// See Folder::saveToSettings for details about why this exists.
|
||||
settings->beginGroup(QLatin1String("Multifolders"));
|
||||
setupFoldersHelper(*settings, account, false);
|
||||
settings->endGroup();
|
||||
|
||||
settings->endGroup(); // <account>
|
||||
}
|
||||
|
||||
@@ -229,6 +227,34 @@ int FolderMan::setupFolders()
|
||||
return _folderMap.size();
|
||||
}
|
||||
|
||||
void FolderMan::setupFoldersHelper(QSettings &settings, AccountStatePtr account, bool backwardsCompatible)
|
||||
{
|
||||
foreach (const auto& folderAlias, settings.childGroups()) {
|
||||
FolderDefinition folderDefinition;
|
||||
if (FolderDefinition::load(settings, folderAlias, &folderDefinition)) {
|
||||
// Migration: Old settings don't have journalPath
|
||||
if (folderDefinition.journalPath.isEmpty()) {
|
||||
folderDefinition.journalPath = folderDefinition.defaultJournalPath(account->account());
|
||||
}
|
||||
folderDefinition.defaultJournalPath(account->account());
|
||||
// Migration: If an old db is found, move it to the new name.
|
||||
if (backwardsCompatible) {
|
||||
SyncJournalDb::maybeMigrateDb(folderDefinition.localPath, folderDefinition.absoluteJournalPath());
|
||||
}
|
||||
|
||||
Folder* f = addFolderInternal(std::move(folderDefinition), account.data());
|
||||
if (f) {
|
||||
// Migration: Mark folders that shall be saved in a backwards-compatible way
|
||||
if (backwardsCompatible) {
|
||||
f->setSaveBackwardsCompatible(true);
|
||||
}
|
||||
scheduleFolder(f);
|
||||
emit folderSyncStateChange(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FolderMan::setupFoldersMigration()
|
||||
{
|
||||
ConfigFile cfg;
|
||||
@@ -259,18 +285,16 @@ int FolderMan::setupFoldersMigration()
|
||||
return _folderMap.size();
|
||||
}
|
||||
|
||||
bool FolderMan::ensureJournalGone(const QString &localPath)
|
||||
bool FolderMan::ensureJournalGone( const QString& journalDbFile )
|
||||
{
|
||||
// FIXME move this to UI, not libowncloudsync
|
||||
// remove old .csync_journal file
|
||||
QString stateDbFile = localPath+QLatin1String("/.csync_journal.db");
|
||||
while (QFile::exists(stateDbFile) && !QFile::remove(stateDbFile)) {
|
||||
qDebug() << "Could not remove old db file at" << stateDbFile;
|
||||
// remove the old journal file
|
||||
while (QFile::exists(journalDbFile) && !QFile::remove(journalDbFile)) {
|
||||
qDebug() << "Could not remove old db file at" << journalDbFile;
|
||||
int ret = QMessageBox::warning(0, tr("Could not reset folder state"),
|
||||
tr("An old sync journal '%1' was found, "
|
||||
"but could not be removed. Please make sure "
|
||||
"that no application is currently using it.")
|
||||
.arg(QDir::fromNativeSeparators(QDir::cleanPath(stateDbFile))),
|
||||
.arg(QDir::fromNativeSeparators(QDir::cleanPath(journalDbFile))),
|
||||
QMessageBox::Retry|QMessageBox::Abort);
|
||||
if (ret == QMessageBox::Abort) {
|
||||
return false;
|
||||
@@ -338,6 +362,7 @@ QString FolderMan::unescapeAlias( const QString& alias )
|
||||
|
||||
// filename is the name of the file only, it does not include
|
||||
// the configuration directory path
|
||||
// WARNING: Do not remove this code, it is used for predefined/automated deployments (2016)
|
||||
Folder* FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountState *accountState )
|
||||
{
|
||||
Folder *folder = 0;
|
||||
@@ -408,6 +433,8 @@ Folder* FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountStat
|
||||
//migrate settings
|
||||
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList);
|
||||
settings.remove(QLatin1String("blackList"));
|
||||
// FIXME: If you remove this codepath, you need to provide another way to do
|
||||
// this via theme.h or the normal FolderMan::setupFolders
|
||||
}
|
||||
|
||||
folder->saveToSettings();
|
||||
@@ -670,12 +697,11 @@ void FolderMan::slotStartScheduledFolderSync()
|
||||
}
|
||||
|
||||
// Find the first folder in the queue that can be synced.
|
||||
Folder* f = 0;
|
||||
Folder* folder = 0;
|
||||
while( !_scheduledFolders.isEmpty() ) {
|
||||
f = _scheduledFolders.dequeue();
|
||||
Q_ASSERT(f);
|
||||
|
||||
if( f->canSync() ) {
|
||||
Folder* g = _scheduledFolders.dequeue();
|
||||
if( g->canSync() ) {
|
||||
folder = g;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -683,9 +709,9 @@ void FolderMan::slotStartScheduledFolderSync()
|
||||
emit scheduleQueueChanged();
|
||||
|
||||
// Start syncing this folder!
|
||||
if( f ) {
|
||||
_currentSyncFolder = f;
|
||||
f->startSync( QStringList() );
|
||||
if( folder ) {
|
||||
_currentSyncFolder = folder;
|
||||
folder->startSync( QStringList() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -831,11 +857,27 @@ void FolderMan::slotFolderSyncFinished( const SyncResult& )
|
||||
|
||||
Folder* FolderMan::addFolder(AccountState* accountState, const FolderDefinition& folderDefinition)
|
||||
{
|
||||
if (!ensureJournalGone(folderDefinition.localPath)) {
|
||||
// Choose a db filename
|
||||
auto definition = folderDefinition;
|
||||
definition.journalPath = definition.defaultJournalPath(accountState->account());
|
||||
|
||||
if (!ensureJournalGone(definition.absoluteJournalPath())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto folder = addFolderInternal(folderDefinition, accountState);
|
||||
auto folder = addFolderInternal(definition, accountState);
|
||||
|
||||
// Migration: The first account that's configured for a local folder shall
|
||||
// be saved in a backwards-compatible way.
|
||||
bool oneAccountOnly = true;
|
||||
foreach (Folder* other, FolderMan::instance()->map()) {
|
||||
if (other != folder && other->cleanPath() == folder->cleanPath()) {
|
||||
oneAccountOnly = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
folder->setSaveBackwardsCompatible(oneAccountOnly);
|
||||
|
||||
if(folder) {
|
||||
folder->saveToSettings();
|
||||
emit folderSyncStateChange(folder);
|
||||
@@ -844,7 +886,8 @@ Folder* FolderMan::addFolder(AccountState* accountState, const FolderDefinition&
|
||||
return folder;
|
||||
}
|
||||
|
||||
Folder* FolderMan::addFolderInternal(FolderDefinition folderDefinition, AccountState* accountState)
|
||||
Folder* FolderMan::addFolderInternal(FolderDefinition folderDefinition,
|
||||
AccountState* accountState)
|
||||
{
|
||||
auto alias = folderDefinition.alias;
|
||||
int count = 0;
|
||||
@@ -1207,17 +1250,16 @@ QString FolderMan::statusToString( SyncResult syncStatus, bool paused ) const
|
||||
return folderMessage;
|
||||
}
|
||||
|
||||
QString FolderMan::checkPathValidityForNewFolder(const QString& path, bool forNewDirectory)
|
||||
QString FolderMan::checkPathValidityForNewFolder(const QString& path, const QUrl &serverUrl, bool forNewDirectory)
|
||||
{
|
||||
if (path.isEmpty()) {
|
||||
return tr("No valid folder selected!");
|
||||
}
|
||||
|
||||
QFileInfo selFile( path );
|
||||
QString userInput = selFile.canonicalFilePath();
|
||||
|
||||
if (!selFile.exists()) {
|
||||
return checkPathValidityForNewFolder(selFile.dir().path(), true);
|
||||
return checkPathValidityForNewFolder(selFile.dir().path(), serverUrl, true);
|
||||
}
|
||||
|
||||
if( !selFile.isDir() ) {
|
||||
@@ -1229,6 +1271,10 @@ QString FolderMan::checkPathValidityForNewFolder(const QString& path, bool forNe
|
||||
}
|
||||
|
||||
// check if the local directory isn't used yet in another ownCloud sync
|
||||
Qt::CaseSensitivity cs = Qt::CaseSensitive;
|
||||
if( Utility::fsCasePreserving() ) {
|
||||
cs = Qt::CaseInsensitive;
|
||||
}
|
||||
|
||||
for (auto i = _folderMap.constBegin(); i != _folderMap.constEnd(); ++i ) {
|
||||
Folder *f = static_cast<Folder*>(i.value());
|
||||
@@ -1236,39 +1282,60 @@ QString FolderMan::checkPathValidityForNewFolder(const QString& path, bool forNe
|
||||
if( folderDir.isEmpty() ) {
|
||||
continue;
|
||||
}
|
||||
if( ! folderDir.endsWith(QLatin1Char('/')) ) folderDir.append(QLatin1Char('/'));
|
||||
if( ! folderDir.endsWith(QLatin1Char('/'), cs) ) folderDir.append(QLatin1Char('/'));
|
||||
|
||||
if (QDir::cleanPath(f->path()) == QDir::cleanPath(userInput)
|
||||
&& QDir::cleanPath(QDir(f->path()).canonicalPath()) == QDir(userInput).canonicalPath()) {
|
||||
return tr("The local folder %1 is already used in a folder sync connection. "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(userInput));
|
||||
}
|
||||
if (!forNewDirectory && QDir::cleanPath(folderDir).startsWith(QDir::cleanPath(userInput)+'/')) {
|
||||
const QString folderDirClean = QDir::cleanPath(folderDir)+'/';
|
||||
const QString userDirClean = QDir::cleanPath(path)+'/';
|
||||
|
||||
// folderDir follows sym links, path not.
|
||||
bool differentPathes = !Utility::fileNamesEqual(QDir::cleanPath(folderDir), QDir::cleanPath(path));
|
||||
|
||||
if (!forNewDirectory && differentPathes && folderDirClean.startsWith(userDirClean,cs)) {
|
||||
return tr("The local folder %1 already contains a folder used in a folder sync connection. "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(userInput));
|
||||
.arg(QDir::toNativeSeparators(path));
|
||||
}
|
||||
|
||||
QString absCleanUserFolder = QDir::cleanPath(QDir(userInput).canonicalPath())+'/';
|
||||
if (!forNewDirectory && QDir::cleanPath(folderDir).startsWith(absCleanUserFolder) ) {
|
||||
return tr("The local folder %1 is a symbolic link. "
|
||||
"The link target already contains a folder used in a folder sync connection. "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(userInput));
|
||||
}
|
||||
// QDir::cleanPath keeps links
|
||||
// canonicalPath() remove symlinks and uses the symlink targets.
|
||||
QString absCleanUserFolder = QDir::cleanPath(QDir(path).canonicalPath())+'/';
|
||||
|
||||
if (QDir::cleanPath(QString(userInput)).startsWith( QDir::cleanPath(folderDir)+'/')) {
|
||||
if ( (forNewDirectory || differentPathes) && userDirClean.startsWith( folderDirClean, cs )) {
|
||||
return tr("The local folder %1 is already contained in a folder used in a folder sync connection. "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(userInput));
|
||||
.arg(QDir::toNativeSeparators(path));
|
||||
}
|
||||
|
||||
if (absCleanUserFolder.startsWith( QDir::cleanPath(folderDir)+'/')) {
|
||||
// both follow symlinks.
|
||||
bool cleanUserEqualsCleanFolder = Utility::fileNamesEqual(absCleanUserFolder, folderDirClean );
|
||||
if (differentPathes && absCleanUserFolder.startsWith( folderDirClean, cs ) &&
|
||||
! cleanUserEqualsCleanFolder ) {
|
||||
return tr("The local folder %1 is a symbolic link. "
|
||||
"The link target is already contained in a folder used in a folder sync connection. "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(userInput));
|
||||
.arg(QDir::toNativeSeparators(path));
|
||||
}
|
||||
|
||||
if (differentPathes && folderDirClean.startsWith(absCleanUserFolder, cs) &&
|
||||
!cleanUserEqualsCleanFolder && !forNewDirectory ) {
|
||||
return tr("The local folder %1 contains a symbolic link. "
|
||||
"The link target contains an already synced folder "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(path));
|
||||
}
|
||||
|
||||
// if both pathes are equal, the server url needs to be different
|
||||
// otherwise it would mean that a new connection from the same local folder
|
||||
// to the same account is added which is not wanted. The account must differ.
|
||||
if( serverUrl.isValid() && Utility::fileNamesEqual(absCleanUserFolder,folderDir ) ) {
|
||||
QUrl folderUrl = f->accountState()->account()->url();
|
||||
QString user = f->accountState()->account()->credentials()->user();
|
||||
folderUrl.setUserName(user);
|
||||
|
||||
if( serverUrl == folderUrl ) {
|
||||
return tr("There is already a sync from the server to this local folder. "
|
||||
"Please pick another local folder!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,11 +97,11 @@ public:
|
||||
Folder* setupFolderFromOldConfigFile(const QString &, AccountState *account );
|
||||
|
||||
/**
|
||||
* Ensures that a given directory does not contain a .csync_journal.
|
||||
* Ensures that a given directory does not contain a sync journal file.
|
||||
*
|
||||
* @returns false if the journal could not be removed, true otherwise.
|
||||
*/
|
||||
static bool ensureJournalGone(const QString &path);
|
||||
static bool ensureJournalGone(const QString& journalDbFile);
|
||||
|
||||
/** Creates a new and empty local directory. */
|
||||
bool startFromScratch( const QString& );
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
*
|
||||
* @returns an empty string if it is allowed, or an error if it is not allowed
|
||||
*/
|
||||
QString checkPathValidityForNewFolder(const QString &path, bool forNewDirectory = false);
|
||||
QString checkPathValidityForNewFolder(const QString &path, const QUrl& serverUrl = QUrl(), bool forNewDirectory = false);
|
||||
|
||||
/**
|
||||
* While ignoring hidden files can theoretically be switched per folder,
|
||||
@@ -257,7 +257,8 @@ private:
|
||||
/** Adds a new folder, does not add it to the account settings and
|
||||
* does not set an account on the new folder.
|
||||
*/
|
||||
Folder* addFolderInternal(FolderDefinition folderDefinition, AccountState* accountState);
|
||||
Folder* addFolderInternal(FolderDefinition folderDefinition,
|
||||
AccountState* accountState);
|
||||
|
||||
/* unloads a folder object, does not delete it */
|
||||
void unloadFolder( Folder * );
|
||||
@@ -273,6 +274,8 @@ private:
|
||||
// restarts the application (Linux only)
|
||||
void restartApplication();
|
||||
|
||||
void setupFoldersHelper(QSettings& settings, AccountStatePtr account, bool backwardsCompatible);
|
||||
|
||||
QSet<Folder*> _disabledFolders;
|
||||
Folder::Map _folderMap;
|
||||
QString _folderConfigPath;
|
||||
|
||||
@@ -295,7 +295,11 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
pBRect.setHeight(barHeight);
|
||||
pBRect.setWidth( overallWidth - 2 * margin );
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
QStyleOptionProgressBarV2 pBarOpt;
|
||||
#else
|
||||
QStyleOptionProgressBar pBarOpt;
|
||||
#endif
|
||||
|
||||
pBarOpt.state = option.state | QStyle::State_Horizontal;
|
||||
pBarOpt.minimum = 0;
|
||||
|
||||
@@ -38,6 +38,12 @@ FolderStatusModel::FolderStatusModel(QObject *parent)
|
||||
FolderStatusModel::~FolderStatusModel()
|
||||
{ }
|
||||
|
||||
static bool sortByFolderHeader(const FolderStatusModel::SubFolderInfo& lhs, const FolderStatusModel::SubFolderInfo& rhs)
|
||||
{
|
||||
return QString::compare(lhs._folder->shortGuiRemotePathOrAppName(),
|
||||
rhs._folder->shortGuiRemotePathOrAppName(),
|
||||
Qt::CaseInsensitive) < 0;
|
||||
}
|
||||
|
||||
void FolderStatusModel::setAccountState(const AccountState* accountState)
|
||||
{
|
||||
@@ -58,7 +64,6 @@ void FolderStatusModel::setAccountState(const AccountState* accountState)
|
||||
if (f->accountState() != accountState)
|
||||
continue;
|
||||
SubFolderInfo info;
|
||||
info._pathIdx << _folders.size();
|
||||
info._name = f->alias();
|
||||
info._path = "/";
|
||||
info._folder = f;
|
||||
@@ -69,6 +74,14 @@ void FolderStatusModel::setAccountState(const AccountState* accountState)
|
||||
connect(f, SIGNAL(newBigFolderDiscovered(QString)), this, SLOT(slotNewBigFolder()), Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
// Sort by header text
|
||||
qSort(_folders.begin(), _folders.end(), sortByFolderHeader);
|
||||
|
||||
// Set the root _pathIdx after the sorting
|
||||
for (int i = 0; i < _folders.size(); ++i) {
|
||||
_folders[i]._pathIdx << i;
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
emit dirtyChanged();
|
||||
}
|
||||
@@ -375,12 +388,13 @@ QModelIndex FolderStatusModel::indexForPath(Folder *f, const QString& path) cons
|
||||
if (slashPos == -1) {
|
||||
// first level folder
|
||||
for (int i = 0; i < _folders.size(); ++i) {
|
||||
if (_folders.at(i)._folder == f) {
|
||||
auto& info = _folders.at(i);
|
||||
if (info._folder == f) {
|
||||
if( path.isEmpty() ) { // the folder object
|
||||
return index(i, 0);
|
||||
}
|
||||
for (int j = 0; j < _folders.at(i)._subs.size(); ++j) {
|
||||
const QString subName = _folders.at(i)._subs.at(j)._name;
|
||||
for (int j = 0; j < info._subs.size(); ++j) {
|
||||
const QString subName = info._subs.at(j)._name;
|
||||
if (subName == path) {
|
||||
return index(j, 0, index(i));
|
||||
}
|
||||
@@ -792,25 +806,6 @@ void FolderStatusModel::slotApplySelectiveSync()
|
||||
resetFolders();
|
||||
}
|
||||
|
||||
static QString shortenFilename( Folder *f, const QString& file )
|
||||
{
|
||||
// strip off the server prefix from the file name
|
||||
QString shortFile(file);
|
||||
if( shortFile.isEmpty() ) {
|
||||
return QString::null;
|
||||
}
|
||||
|
||||
if(shortFile.startsWith(QLatin1String("ownclouds://")) ||
|
||||
shortFile.startsWith(QLatin1String("owncloud://")) ) {
|
||||
// rip off the whole ownCloud URL.
|
||||
if( f ) {
|
||||
QString remotePathUrl = f->remoteUrl().toString();
|
||||
shortFile.remove(Utility::toCSyncScheme(remotePathUrl));
|
||||
}
|
||||
}
|
||||
return shortFile;
|
||||
}
|
||||
|
||||
void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
|
||||
{
|
||||
auto par = qobject_cast<QWidget*>(QObject::parent());
|
||||
@@ -884,7 +879,7 @@ void FolderStatusModel::slotSetProgress(const ProgressInfo &progress)
|
||||
curItemProgress = curItem._size;
|
||||
}
|
||||
|
||||
QString itemFileName = shortenFilename(f, curItem._file);
|
||||
QString itemFileName = curItem._file;
|
||||
QString kindString = Progress::asActionString(curItem);
|
||||
|
||||
QString fileProgressString;
|
||||
@@ -986,10 +981,12 @@ void FolderStatusModel::slotFolderSyncStateChange(Folder *f)
|
||||
}
|
||||
if (folderIndex < 0) { return; }
|
||||
|
||||
auto& pi = _folders[folderIndex]._progress;
|
||||
|
||||
SyncResult::Status state = f->syncResult().status();
|
||||
if (f->syncPaused()) {
|
||||
// Reset progress info.
|
||||
_folders[folderIndex]._progress = SubFolderInfo::Progress();
|
||||
pi = SubFolderInfo::Progress();
|
||||
} else if (state == SyncResult::NotYetStarted) {
|
||||
FolderMan* folderMan = FolderMan::instance();
|
||||
int pos = folderMan->scheduleQueue().indexOf(f);
|
||||
@@ -1003,16 +1000,16 @@ void FolderStatusModel::slotFolderSyncStateChange(Folder *f)
|
||||
} else {
|
||||
message = tr("Waiting for %n other folder(s)...", "", pos);
|
||||
}
|
||||
_folders[folderIndex]._progress = SubFolderInfo::Progress();
|
||||
_folders[folderIndex]._progress._overallSyncString = message;
|
||||
pi = SubFolderInfo::Progress();
|
||||
pi._overallSyncString = message;
|
||||
} else if (state == SyncResult::SyncPrepare) {
|
||||
_folders[folderIndex]._progress = SubFolderInfo::Progress();
|
||||
_folders[folderIndex]._progress._overallSyncString = tr("Preparing to sync...");
|
||||
pi = SubFolderInfo::Progress();
|
||||
pi._overallSyncString = tr("Preparing to sync...");
|
||||
} else if (state == SyncResult::Problem || state == SyncResult::Success) {
|
||||
// Reset the progress info after a sync.
|
||||
_folders[folderIndex]._progress = SubFolderInfo::Progress();
|
||||
pi = SubFolderInfo::Progress();
|
||||
} else if (state == SyncResult::Error) {
|
||||
_folders[folderIndex]._progress = SubFolderInfo::Progress();
|
||||
pi = SubFolderInfo::Progress();
|
||||
}
|
||||
|
||||
// update the icon etc. now
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
@@ -168,7 +169,8 @@ void FolderWatcherPrivate::slotReceivedNotification(int fd)
|
||||
if (event->len > 0 && event->wd > -1) {
|
||||
QByteArray fileName(event->name);
|
||||
// qDebug() << Q_FUNC_INFO << event->name;
|
||||
if (fileName.startsWith(".csync_journal.db") ||
|
||||
if (fileName.startsWith("._sync_") ||
|
||||
fileName.startsWith(".csync_journal.db") ||
|
||||
fileName.startsWith(".owncloudsync.log")) {
|
||||
// qDebug() << "ignore journal";
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -56,8 +56,9 @@ QString FormatWarningsWizardPage::formatWarnings(const QStringList &warnings) co
|
||||
return ret;
|
||||
}
|
||||
|
||||
FolderWizardLocalPath::FolderWizardLocalPath()
|
||||
: FormatWarningsWizardPage()
|
||||
FolderWizardLocalPath::FolderWizardLocalPath(const AccountPtr& account)
|
||||
: FormatWarningsWizardPage(),
|
||||
_account(account)
|
||||
{
|
||||
_ui.setupUi(this);
|
||||
registerField(QLatin1String("sourceFolder*"), _ui.localFolderLineEdit);
|
||||
@@ -89,8 +90,13 @@ void FolderWizardLocalPath::cleanupPage()
|
||||
|
||||
bool FolderWizardLocalPath::isComplete() const
|
||||
{
|
||||
QUrl serverUrl = _account->url();
|
||||
serverUrl.setUserName( _account->credentials()->user() );
|
||||
|
||||
QString errorStr = FolderMan::instance()->checkPathValidityForNewFolder(
|
||||
QDir::fromNativeSeparators(_ui.localFolderLineEdit->text()));
|
||||
QDir::fromNativeSeparators(_ui.localFolderLineEdit->text()), serverUrl);
|
||||
|
||||
|
||||
|
||||
bool isOk = errorStr.isEmpty();
|
||||
QStringList warnStrings;
|
||||
@@ -133,7 +139,7 @@ void FolderWizardLocalPath::slotChooseLocalFolder()
|
||||
}
|
||||
|
||||
// =================================================================================
|
||||
FolderWizardRemotePath::FolderWizardRemotePath(AccountPtr account)
|
||||
FolderWizardRemotePath::FolderWizardRemotePath(const AccountPtr& account)
|
||||
: FormatWarningsWizardPage()
|
||||
,_warnWasVisible(false)
|
||||
,_account(account)
|
||||
@@ -473,7 +479,7 @@ void FolderWizardRemotePath::showWarn( const QString& msg ) const
|
||||
|
||||
// ====================================================================================
|
||||
|
||||
FolderWizardSelectiveSync::FolderWizardSelectiveSync(AccountPtr account)
|
||||
FolderWizardSelectiveSync::FolderWizardSelectiveSync(const AccountPtr& account)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
_treeView = new SelectiveSyncTreeView(account, this);
|
||||
@@ -527,7 +533,7 @@ void FolderWizardSelectiveSync::cleanupPage()
|
||||
|
||||
FolderWizard::FolderWizard(AccountPtr account, QWidget *parent)
|
||||
: QWizard(parent),
|
||||
_folderWizardSourcePage(new FolderWizardLocalPath),
|
||||
_folderWizardSourcePage(new FolderWizardLocalPath(account)),
|
||||
_folderWizardTargetPage(0),
|
||||
_folderWizardSelectiveSyncPage(new FolderWizardSelectiveSync(account))
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@ class FolderWizardLocalPath : public FormatWarningsWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FolderWizardLocalPath();
|
||||
explicit FolderWizardLocalPath(const AccountPtr& account);
|
||||
~FolderWizardLocalPath();
|
||||
|
||||
virtual bool isComplete() const Q_DECL_OVERRIDE;
|
||||
@@ -63,6 +63,7 @@ protected slots:
|
||||
private:
|
||||
Ui_FolderWizardSourcePage _ui;
|
||||
Folder::Map _folderMap;
|
||||
AccountPtr _account;
|
||||
};
|
||||
|
||||
|
||||
@@ -75,7 +76,7 @@ class FolderWizardRemotePath : public FormatWarningsWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FolderWizardRemotePath(AccountPtr account);
|
||||
explicit FolderWizardRemotePath(const AccountPtr& account);
|
||||
~FolderWizardRemotePath();
|
||||
|
||||
virtual bool isComplete() const Q_DECL_OVERRIDE;
|
||||
@@ -117,7 +118,7 @@ class FolderWizardSelectiveSync : public QWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FolderWizardSelectiveSync(AccountPtr account);
|
||||
explicit FolderWizardSelectiveSync(const AccountPtr& account);
|
||||
~FolderWizardSelectiveSync();
|
||||
|
||||
virtual bool validatePage() Q_DECL_OVERRIDE;
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "winuser.h"
|
||||
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "owncloud.exe.manifest-mingw"
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
+2
-1
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário