175 fprintf(stderr, " trash-info <directory>\n"); |
175 fprintf(stderr, " trash-info <directory>\n"); |
176 fprintf(stderr, " empty-trash <directory>\n"); |
176 fprintf(stderr, " empty-trash <directory>\n"); |
177 fprintf(stderr, " add-tag [-s <syncdir>] <file> <tag>\n"); |
177 fprintf(stderr, " add-tag [-s <syncdir>] <file> <tag>\n"); |
178 fprintf(stderr, " remove-tag [-s <syncdir>] <file> <tag>\n"); |
178 fprintf(stderr, " remove-tag [-s <syncdir>] <file> <tag>\n"); |
179 fprintf(stderr, " update-tags [-s <syncdir>] <file> [tags]\n"); |
179 fprintf(stderr, " update-tags [-s <syncdir>] <file> [tags]\n"); |
180 fprintf(stderr, " update-tags [-s <syncdir>] <file>\n\n"); |
180 fprintf(stderr, " list-tags [-s <syncdir>] <file>\n\n"); |
181 |
181 |
182 fprintf(stderr, "Options:\n"); |
182 fprintf(stderr, "Options:\n"); |
183 fprintf(stderr, " -c Disable conflict detection\n"); |
183 fprintf(stderr, " -c Disable conflict detection\n"); |
184 fprintf(stderr, " -l Lock the repository before access\n"); |
184 fprintf(stderr, " -l Lock the repository before access\n"); |
185 fprintf(stderr, " -d Don't lock the repository\n"); |
185 fprintf(stderr, " -d Don't lock the repository\n"); |
1350 ucx_map_free(tag_map); |
1350 ucx_map_free(tag_map); |
1351 |
1351 |
1352 return new_tags; |
1352 return new_tags; |
1353 } |
1353 } |
1354 |
1354 |
|
1355 int sync_tags_equal(UcxList *tags1, UcxList *tags2) { |
|
1356 if(!tags1) { |
|
1357 return tags2 ? 0 : 1; |
|
1358 } |
|
1359 if(!tags2) { |
|
1360 return tags1 ? 0 : 1; |
|
1361 } |
|
1362 |
|
1363 UcxMap *map1 = ucx_map_new(32); |
|
1364 UCX_FOREACH(elm, tags1) { |
|
1365 DavTag *t = elm->data; |
|
1366 ucx_map_cstr_put(map1, t->name, t); |
|
1367 } |
|
1368 |
|
1369 int equal = 1; |
|
1370 int i = 0; |
|
1371 UCX_FOREACH(elm, tags2) { |
|
1372 DavTag *t = elm->data; |
|
1373 if(!ucx_map_cstr_get(map1, t->name)) { |
|
1374 equal = 0; |
|
1375 break; |
|
1376 } |
|
1377 i++; |
|
1378 } |
|
1379 |
|
1380 if(i != map1->count) { |
|
1381 equal = 0; |
|
1382 } |
|
1383 ucx_map_free(map1); |
|
1384 return equal; |
|
1385 } |
|
1386 |
1355 int sync_store_tags(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res) { |
1387 int sync_store_tags(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res) { |
1356 if(!dir->tagconfig) { |
1388 if(!dir->tagconfig) { |
1357 return 0; |
1389 return 0; |
1358 } |
1390 } |
1359 |
1391 |
1364 tags = parse_dav_xml_taglist(tagsprop); |
1396 tags = parse_dav_xml_taglist(tagsprop); |
1365 |
1397 |
1366 } |
1398 } |
1367 } |
1399 } |
1368 |
1400 |
1369 DavBool store_empty_tags = FALSE; |
1401 DavBool store_tags = FALSE; |
1370 if(dir->tagconfig->conflict != TAG_NO_CONFLICT) { |
1402 DavBool tags_changed = FALSE; |
1371 DavBool tags_changed = FALSE; |
1403 UcxList *local_tags = sync_get_file_tags(dir, local, &tags_changed); |
1372 UcxList *local_tags = sync_get_file_tags(dir, local, &tags_changed); |
1404 if(tags_changed) { |
1373 if(tags_changed) { |
1405 switch(dir->tagconfig->conflict) { |
1374 switch(dir->tagconfig->conflict) { |
1406 case TAG_NO_CONFLICT: |
1375 case TAG_NO_CONFLICT: |
1407 case TAG_KEEP_LOCAL: { |
1376 case TAG_KEEP_LOCAL: { |
1408 store_tags = FALSE; |
1377 store_empty_tags = TRUE; |
1409 break; |
1378 tags = local_tags; |
1410 } |
1379 // TODO: free tags |
1411 case TAG_KEEP_REMOTE: { |
1380 break; |
1412 store_tags = TRUE; |
1381 } |
1413 local->tags_updated = FALSE; |
1382 case TAG_KEEP_REMOTE: break; |
1414 } |
1383 case TAG_MERGE: { |
1415 case TAG_MERGE: { |
1384 UcxList *new_tags = sync_merge_tags(local_tags, tags); |
1416 UcxList *new_tags = sync_merge_tags(local_tags, tags); |
1385 // TODO: free tags and local_tags |
1417 // TODO: free tags and local_tags |
1386 tags = new_tags; |
1418 tags = new_tags; |
1387 store_empty_tags = TRUE; |
1419 store_tags = TRUE; |
1388 // make sure the merged tags will be pushed the next time |
1420 // make sure the merged tags will be pushed the next time |
1389 local->tags_updated = TRUE; |
1421 local->tags_updated = TRUE; |
1390 break; |
1422 break; |
1391 } |
1423 } |
1392 } |
1424 } |
1393 } else { |
1425 } else { |
1394 // TODO: free local_tags |
1426 if(!sync_tags_equal(tags, local_tags)) { |
1395 } |
1427 store_tags = TRUE; |
1396 } |
1428 } |
1397 |
1429 // TODO: free local_tags |
1398 if(!tags && !store_empty_tags) { |
1430 } |
|
1431 |
|
1432 if(!store_tags) { |
1399 return 0; |
1433 return 0; |
1400 } |
1434 } |
1401 |
1435 |
1402 int ret = sync_store_tags_local(dir, local, path, tags); |
1436 int ret = sync_store_tags_local(dir, local, path, tags); |
1403 |
1437 |
1431 char *data_hash = dav_create_hash(data->space, data->size); |
1465 char *data_hash = dav_create_hash(data->space, data->size); |
1432 int update = 1; |
1466 int update = 1; |
1433 if(local) { |
1467 if(local) { |
1434 if(!local->tags_hash || strcmp(data_hash, local->tags_hash)) { |
1468 if(!local->tags_hash || strcmp(data_hash, local->tags_hash)) { |
1435 printf("update: %s\n", local->path); |
1469 printf("update: %s\n", local->path); |
1436 // TODO: update hash in localres?? |
|
1437 } else { |
1470 } else { |
1438 update = 0; |
1471 update = 0; |
1439 } |
1472 } |
1440 } |
1473 } |
1441 if(update) { |
1474 if(update) { |
1442 ret = xattr_set(path, dir->tagconfig->xattr_name, data->space, data->pos); |
1475 ret = xattr_set(path, dir->tagconfig->xattr_name, data->space, data->pos); |
|
1476 if(local) { |
|
1477 if(local->tags_hash) { |
|
1478 free(local->tags_hash); |
|
1479 } |
|
1480 local->tags_hash = data_hash; |
|
1481 } |
|
1482 } else { |
|
1483 free(data_hash); |
1443 } |
1484 } |
1444 ucx_buffer_free(data); |
1485 ucx_buffer_free(data); |
1445 } else { |
1486 } else { |
1446 ret = -1; |
1487 ret = -1; |
1447 } |
1488 } |
1448 } else { |
1489 } else { |
1449 // TODO: delete xattr |
1490 if(local) { |
1450 //ret = xattr_remove(path, dir->tagconfig->xattr_name); |
1491 printf("update: %s\n", local->path); |
|
1492 } |
|
1493 ret = xattr_remove(path, dir->tagconfig->xattr_name); |
1451 } |
1494 } |
1452 } |
1495 } |
1453 |
1496 |
1454 return ret; |
1497 return ret; |
1455 } |
1498 } |
2178 if(sync_store_tags_local(file.dir, NULL, path, tags)) { |
2224 if(sync_store_tags_local(file.dir, NULL, path, tags)) { |
2179 fprintf(stderr, "Cannot store tags\n"); |
2225 fprintf(stderr, "Cannot store tags\n"); |
2180 } |
2226 } |
2181 if(localres) { |
2227 if(localres) { |
2182 localres->tags_updated = TRUE; |
2228 localres->tags_updated = TRUE; |
|
2229 if(!tags) { |
|
2230 if(localres->tags_hash) { |
|
2231 free(localres->tags_hash); |
|
2232 } |
|
2233 localres->tags_hash = NULL; |
|
2234 } |
2183 } |
2235 } |
2184 } |
2236 } |
2185 |
2237 |
2186 // store db |
2238 // store db |
2187 if(store_db(db, file.dir->database)) { |
2239 if(store_db(db, file.dir->database)) { |