972 } |
972 } |
973 |
973 |
974 if(dir->tagconfig && local_res->tags_updated && !abort) { |
974 if(dir->tagconfig && local_res->tags_updated && !abort) { |
975 // get tags from tagstore (xattr or something else) |
975 // get tags from tagstore (xattr or something else) |
976 // and store it in resource property |
976 // and store it in resource property |
977 UcxList *tags = sync_get_file_tags(dir, local_res); |
977 UcxList *tags = sync_get_file_tags(dir, local_res, NULL); |
978 DavXmlNode *prop = create_xml_taglist(tags); |
978 DavXmlNode *prop = create_xml_taglist(tags); |
979 if(prop) { |
979 if(prop) { |
980 dav_set_property_ns(res, DAV_NS, "tags", prop); |
980 dav_set_property_ns(res, DAV_NS, "tags", prop); |
981 printf("update: %s\n", local_res->path); |
981 printf("update: %s\n", local_res->path); |
982 if(dav_store(res)) { |
982 if(dav_store(res)) { |
1246 res->tags_updated = db_res->tags_updated; |
1246 res->tags_updated = db_res->tags_updated; |
1247 if(db_res->etag) { |
1247 if(db_res->etag) { |
1248 res->etag = strdup(db_res->etag); |
1248 res->etag = strdup(db_res->etag); |
1249 } |
1249 } |
1250 |
1250 |
1251 if(dir->tagconfig && dir->tagconfig->scan && !res->tags_updated) { |
1251 if(dir->tagconfig && dir->tagconfig->detect_changes && !res->tags_updated) { |
1252 UcxBuffer *tags = sync_get_file_tag_data(dir, res); |
1252 UcxBuffer *tags = sync_get_file_tag_data(dir, res); |
1253 if(tags) { |
1253 if(tags) { |
1254 if(db_res->tags_hash) { |
1254 if(db_res->tags_hash) { |
1255 char *hash = dav_create_hash(tags->space, tags->size); |
1255 char *hash = dav_create_hash(tags->space, tags->size); |
1256 if(strcmp(hash, db_res->tags_hash)) { |
1256 if(strcmp(hash, db_res->tags_hash)) { |
1328 if(tagsprop) { |
1328 if(tagsprop) { |
1329 tags = parse_dav_xml_taglist(tagsprop); |
1329 tags = parse_dav_xml_taglist(tagsprop); |
1330 } |
1330 } |
1331 } |
1331 } |
1332 |
1332 |
1333 if(!tags) { |
1333 DavBool store_empty_tags = FALSE; |
|
1334 if(dir->tagconfig->conflict != TAG_NO_CONFLICT) { |
|
1335 DavBool tags_changed = FALSE; |
|
1336 UcxList *local_tags = sync_get_file_tags(dir, local, &tags_changed); |
|
1337 if(tags_changed) { |
|
1338 switch(dir->tagconfig->conflict) { |
|
1339 case TAG_KEEP_LOCAL: { |
|
1340 store_empty_tags = TRUE; |
|
1341 tags = local_tags; |
|
1342 // TODO: free tags |
|
1343 break; |
|
1344 } |
|
1345 case TAG_KEEP_REMOTE: break; |
|
1346 case TAG_MERGE: { |
|
1347 // this map is used to check the existence of tags |
|
1348 UcxMap *tag_map = ucx_map_new(32); |
|
1349 // merged taglist |
|
1350 UcxList *new_tags = NULL; |
|
1351 |
|
1352 // add all local tags |
|
1353 UCX_FOREACH(elm, local_tags) { |
|
1354 DavTag *t = elm->data; |
|
1355 ucx_map_cstr_put(tag_map, t->name, t); |
|
1356 DavTag *newt = calloc(1, sizeof(DavTag)); |
|
1357 newt->color = t->color ? strdup(t->color) : NULL; |
|
1358 newt->name = strdup(t->name); |
|
1359 new_tags = ucx_list_append(new_tags, newt); |
|
1360 } |
|
1361 // check if a remote tag is already in the map |
|
1362 // and if not add it to the new taglist |
|
1363 UCX_FOREACH(elm, tags) { |
|
1364 DavTag *t = elm->data; |
|
1365 if(!ucx_map_cstr_get(tag_map, t->name)) { |
|
1366 DavTag *newt = calloc(1, sizeof(DavTag)); |
|
1367 newt->color = t->color ? strdup(t->color) : NULL; |
|
1368 newt->name = strdup(t->name); |
|
1369 new_tags = ucx_list_append(new_tags, newt); |
|
1370 } |
|
1371 } |
|
1372 |
|
1373 ucx_map_free(tag_map); |
|
1374 // TODO: free tags and local_tags |
|
1375 |
|
1376 tags = new_tags; |
|
1377 |
|
1378 store_empty_tags = TRUE; |
|
1379 |
|
1380 break; |
|
1381 } |
|
1382 } |
|
1383 } else { |
|
1384 // TODO: free local_tags |
|
1385 } |
|
1386 } |
|
1387 |
|
1388 if(!tags && !store_empty_tags) { |
1334 return 0; |
1389 return 0; |
1335 } |
1390 } |
1336 |
1391 |
1337 int ret = 0; |
1392 int ret = 0; |
1338 if(dir->tagconfig->store == TAG_STORE_XATTR) { |
1393 if(dir->tagconfig->store == TAG_STORE_XATTR) { |
1339 UcxBuffer *data = NULL; |
1394 UcxBuffer *data = NULL; |
1340 switch(dir->tagconfig->local_format) { |
1395 if(tags) { |
1341 default: break; |
1396 switch(dir->tagconfig->local_format) { |
1342 case TAG_FORMAT_TEXT: { |
1397 default: break; |
1343 data = create_text_taglist(tags); |
1398 case TAG_FORMAT_TEXT: { |
1344 break; |
1399 data = create_text_taglist(tags); |
1345 } |
1400 break; |
1346 case TAG_FORMAT_CSV: { |
1401 } |
1347 data = create_csv_taglist(tags); |
1402 case TAG_FORMAT_CSV: { |
1348 break; |
1403 data = create_csv_taglist(tags); |
1349 } |
1404 break; |
1350 case TAG_FORMAT_MACOS: { |
1405 } |
1351 data = create_macos_taglist(tags); |
1406 case TAG_FORMAT_MACOS: { |
1352 break; |
1407 data = create_macos_taglist(tags); |
1353 } |
1408 break; |
1354 } |
1409 } |
1355 |
1410 } |
1356 if(data) { |
1411 |
1357 ret = xattr_set(path, "tags", data->space, data->pos); |
1412 if(data) { |
1358 ucx_buffer_free(data); |
1413 ret = xattr_set(path, dir->tagconfig->xattr_name, data->space, data->pos); |
|
1414 ucx_buffer_free(data); |
|
1415 } else { |
|
1416 ret = -1; |
|
1417 } |
1359 } else { |
1418 } else { |
1360 ret = -1; |
1419 // TODO: relete xattr |
|
1420 //ret = xattr_remove(path, dir->tagconfig->xattr_name); |
1361 } |
1421 } |
1362 } |
1422 } |
1363 |
1423 |
1364 // TODO: free stuff |
1424 // TODO: free stuff |
1365 |
1425 |
1374 if(dir->tagconfig->store == TAG_STORE_XATTR) { |
1434 if(dir->tagconfig->store == TAG_STORE_XATTR) { |
1375 ssize_t tag_length = 0; |
1435 ssize_t tag_length = 0; |
1376 char *local_path = util_concat_path(dir->path, res->path); |
1436 char *local_path = util_concat_path(dir->path, res->path); |
1377 char* tag_data = xattr_get( |
1437 char* tag_data = xattr_get( |
1378 local_path, |
1438 local_path, |
1379 dir->tagconfig->local_format == TAG_FORMAT_MACOS ? MACOS_TAG_XATTR : "tags", |
1439 dir->tagconfig->xattr_name, |
1380 &tag_length); |
1440 &tag_length); |
1381 free(local_path); |
1441 free(local_path); |
1382 |
1442 |
1383 if(tag_length > 0) { |
1443 if(tag_length > 0) { |
1384 buf = ucx_buffer_new(tag_data, (size_t)tag_length, UCX_BUFFER_AUTOFREE); |
1444 buf = ucx_buffer_new(tag_data, (size_t)tag_length, UCX_BUFFER_AUTOFREE); |
1398 UcxBuffer *tag_buf = res->cached_tags ? |
1460 UcxBuffer *tag_buf = res->cached_tags ? |
1399 res->cached_tags : |
1461 res->cached_tags : |
1400 sync_get_file_tag_data(dir, res); |
1462 sync_get_file_tag_data(dir, res); |
1401 |
1463 |
1402 if(tag_buf) { |
1464 if(tag_buf) { |
1403 res->tags_hash = dav_create_hash(tag_buf->space, tag_buf->size); |
1465 char *newhash = dav_create_hash(tag_buf->space, tag_buf->size); |
|
1466 if(res->tags_hash) { |
|
1467 if(changed && strcmp(res->tags_hash, newhash)) { |
|
1468 *changed = TRUE; |
|
1469 } |
|
1470 free(res->tags_hash); |
|
1471 } else { |
|
1472 if(changed) *changed = TRUE; |
|
1473 } |
|
1474 res->tags_hash = newhash; |
1404 |
1475 |
1405 switch(dir->tagconfig->local_format) { |
1476 switch(dir->tagconfig->local_format) { |
1406 default: break; |
1477 default: break; |
1407 case TAG_FORMAT_TEXT: { |
1478 case TAG_FORMAT_TEXT: { |
1408 tags = parse_text_taglist(tag_buf->space, tag_buf->size); |
1479 tags = parse_text_taglist(tag_buf->space, tag_buf->size); |
1451 } |
1524 } |
1452 |
1525 |
1453 dav_set_content(res, in, (dav_read_func)fread); |
1526 dav_set_content(res, in, (dav_read_func)fread); |
1454 |
1527 |
1455 if(dir->tagconfig) { |
1528 if(dir->tagconfig) { |
1456 UcxList *tags = sync_get_file_tags(dir, local); |
1529 UcxList *tags = sync_get_file_tags(dir, local, NULL); // TODO: check remote tags |
1457 DavXmlNode *prop = create_xml_taglist(tags); |
1530 DavXmlNode *prop = create_xml_taglist(tags); |
1458 if(prop) { |
1531 if(prop) { |
1459 dav_set_property_ns(res, DAV_NS, "tags", prop); |
1532 dav_set_property_ns(res, DAV_NS, "tags", prop); |
1460 } |
1533 } |
1461 } |
1534 } |