dav/sync.c

changeset 372
2e15ff88a0ab
parent 370
ab9c5afdc243
child 374
38ae05d46f9a
equal deleted inserted replaced
371:604e7e335b3b 372:2e15ff88a0ab
126 ret = cmd_delete_conflicts(args); 126 ret = cmd_delete_conflicts(args);
127 } else if(!strcmp(cmd, "trash-info")) { 127 } else if(!strcmp(cmd, "trash-info")) {
128 ret = cmd_trash_info(args); 128 ret = cmd_trash_info(args);
129 } else if(!strcmp(cmd, "empty-trash")) { 129 } else if(!strcmp(cmd, "empty-trash")) {
130 ret = cmd_empty_trash(args); 130 ret = cmd_empty_trash(args);
131 } else if(!strcmp(cmd, "add-tag")) {
132 ret = cmd_add_tag(args);
133 } else if(!strcmp(cmd, "remove-tag")) {
134 ret = cmd_remove_tag(args);
135 } else if(!strcmp(cmd, "update-tags")) {
136 ret = cmd_update_tags(args);
131 } else if(!strcmp(cmd, "add-dir") 137 } else if(!strcmp(cmd, "add-dir")
132 || !strcmp(cmd, "add-directory")) { 138 || !strcmp(cmd, "add-directory")) {
133 ret = cmd_add_directory(args); 139 ret = cmd_add_directory(args);
134 } else if(!strcmp(cmd, "list-dirs") 140 } else if(!strcmp(cmd, "list-dirs")
135 || !strcmp(cmd, "list-directories")) { 141 || !strcmp(cmd, "list-directories")) {
163 fprintf(stderr, " push [-cld] <directory>\n"); 169 fprintf(stderr, " push [-cld] <directory>\n");
164 fprintf(stderr, " archive [-cld] <directory>\n"); 170 fprintf(stderr, " archive [-cld] <directory>\n");
165 fprintf(stderr, " resolve-conflicts <directory>\n"); 171 fprintf(stderr, " resolve-conflicts <directory>\n");
166 fprintf(stderr, " delete-conflicts <directory>\n"); 172 fprintf(stderr, " delete-conflicts <directory>\n");
167 fprintf(stderr, " trash-info <directory>\n"); 173 fprintf(stderr, " trash-info <directory>\n");
168 fprintf(stderr, " empty-trash <directory>\n\n"); 174 fprintf(stderr, " empty-trash <directory>\n");
175 fprintf(stderr, " add-tag [-s <syncdir>] <file> <tag>\n");
176 fprintf(stderr, " remove-tag [-s <syncdir>] <file> <tag>\n");
177 fprintf(stderr, " update-tags [-s <syncdir>] <file> [tags]\n\n");
169 178
170 fprintf(stderr, "Options:\n"); 179 fprintf(stderr, "Options:\n");
171 fprintf(stderr, " -c Disable conflict detection\n"); 180 fprintf(stderr, " -c Disable conflict detection\n");
172 fprintf(stderr, " -l Lock the repository before access\n"); 181 fprintf(stderr, " -l Lock the repository before access\n");
173 fprintf(stderr, " -d Don't lock the repository\n"); 182 fprintf(stderr, " -d Don't lock the repository\n");
1384 1393
1385 if(!tags && !store_empty_tags) { 1394 if(!tags && !store_empty_tags) {
1386 return 0; 1395 return 0;
1387 } 1396 }
1388 1397
1398 int ret = sync_store_tags_local(dir, local, path, tags);
1399
1400 // TODO: free stuff
1401
1402 return ret;
1403 }
1404
1405 int sync_store_tags_local(SyncDirectory *dir, LocalResource *local, const char *path, UcxList *tags) {
1389 int ret = 0; 1406 int ret = 0;
1390 if(dir->tagconfig->store == TAG_STORE_XATTR) { 1407 if(dir->tagconfig->store == TAG_STORE_XATTR) {
1391 UcxBuffer *data = NULL; 1408 UcxBuffer *data = NULL;
1392 if(tags) { 1409 if(tags) {
1393 switch(dir->tagconfig->local_format) { 1410 switch(dir->tagconfig->local_format) {
1406 } 1423 }
1407 } 1424 }
1408 1425
1409 if(data) { 1426 if(data) {
1410 char *data_hash = dav_create_hash(data->space, data->size); 1427 char *data_hash = dav_create_hash(data->space, data->size);
1411 if(!local->tags_hash || strcmp(data_hash, local->tags_hash)) { 1428 int update = 1;
1412 printf("update: %s\n", local->path); 1429 if(local) {
1430 if(!local->tags_hash || strcmp(data_hash, local->tags_hash)) {
1431 printf("update: %s\n", local->path);
1432 // TODO: update hash in localres??
1433 } else {
1434 update = 0;
1435 }
1436 }
1437 if(update) {
1413 ret = xattr_set(path, dir->tagconfig->xattr_name, data->space, data->pos); 1438 ret = xattr_set(path, dir->tagconfig->xattr_name, data->space, data->pos);
1414 } 1439 }
1415 ucx_buffer_free(data); 1440 ucx_buffer_free(data);
1416 } else { 1441 } else {
1417 ret = -1; 1442 ret = -1;
1419 } else { 1444 } else {
1420 // TODO: relete xattr 1445 // TODO: relete xattr
1421 //ret = xattr_remove(path, dir->tagconfig->xattr_name); 1446 //ret = xattr_remove(path, dir->tagconfig->xattr_name);
1422 } 1447 }
1423 } 1448 }
1424
1425 // TODO: free stuff
1426 1449
1427 return ret; 1450 return ret;
1428 } 1451 }
1429 1452
1430 UcxBuffer* sync_get_file_tag_data(SyncDirectory *dir, LocalResource *res) { 1453 UcxBuffer* sync_get_file_tag_data(SyncDirectory *dir, LocalResource *res) {
1455 1478
1456 UcxList* sync_get_file_tags(SyncDirectory *dir, LocalResource *res, DavBool *changed) { 1479 UcxList* sync_get_file_tags(SyncDirectory *dir, LocalResource *res, DavBool *changed) {
1457 if(changed) *changed = FALSE; 1480 if(changed) *changed = FALSE;
1458 1481
1459 UcxList *tags = NULL; 1482 UcxList *tags = NULL;
1483
1484 if(!res) {
1485 return NULL;
1486 }
1460 1487
1461 if(!dir->tagconfig) { 1488 if(!dir->tagconfig) {
1462 return NULL; 1489 return NULL;
1463 } 1490 }
1464 if(dir->tagconfig->store == TAG_STORE_XATTR) { 1491 if(dir->tagconfig->store == TAG_STORE_XATTR) {
2039 } 2066 }
2040 closedir(dir); 2067 closedir(dir);
2041 2068
2042 return 0; 2069 return 0;
2043 } 2070 }
2071
2072 #define CMD_TAG_ADD 0
2073 #define CMD_TAG_REMOVE 1
2074 #define CMD_TAG_UPDATE 2
2075 int cmd_add_tag(CmdArgs *args) {
2076 if(args->argc != 2) {
2077 fprintf(stderr, "Too %s arguments\n", args->argc <= 1 ? "few" : "many");
2078 return -1;
2079 }
2080 return cmd_tagopt(args, CMD_TAG_ADD);
2081 }
2082
2083 int cmd_remove_tag(CmdArgs *args) {
2084 if(args->argc != 2) {
2085 fprintf(stderr, "Too %s arguments\n", args->argc <= 1 ? "few" : "many");
2086 return -1;
2087 }
2088 return cmd_tagopt(args, CMD_TAG_REMOVE);
2089 }
2090
2091 int cmd_update_tags(CmdArgs *args) {
2092 if(args->argc < 1 || args->argc > 2) {
2093 fprintf(stderr, "Too %s arguments\n", args->argc < 1 ? "few" : "many");
2094 return -1;
2095 }
2096 return cmd_tagopt(args, CMD_TAG_UPDATE);
2097 }
2098
2099 int cmd_tagopt(CmdArgs *args, int cmd) {
2100 SyncFile file;
2101 int ret = 0;
2102 char *path = args->argv[0];
2103
2104 int err = sync_get_file(args, path, NULL, &file);
2105 if(err) {
2106 fprintf(stderr, "err: %d\n", err); // TODO: print nice err msg
2107 return -1;
2108 }
2109
2110 if(!file.dir->tagconfig) {
2111 fprintf(stderr, "Tags are not supported for this sync directory\n");
2112 return -1;
2113 }
2114
2115 SyncDatabase *db = load_db(file.dir->database);
2116 if(!db) {
2117 fprintf(stderr, "Cannot load sync directory database\n");
2118 return -1;
2119 }
2120
2121 LocalResource *localres = ucx_map_cstr_get(db->resources, file.path);
2122 UcxList *tags = NULL;
2123 DavBool store_tags = FALSE;
2124
2125 if(cmd == CMD_TAG_ADD || cmd == CMD_TAG_REMOVE) {
2126 char *tag = args->argv[1];
2127 char *tagcolor = NULL; // TODO: get color
2128
2129 tags = sync_get_file_tags(file.dir, localres, NULL);
2130 UcxList *x = NULL;
2131 UCX_FOREACH(elm, tags) {
2132 DavTag *t = elm->data;
2133 if(!strcmp(t->name, tag)) {
2134 x = elm;
2135 break;
2136 }
2137 }
2138
2139 if(cmd == CMD_TAG_ADD) {
2140 if(!x) {
2141 DavTag *newtag = malloc(sizeof(DavTag));
2142 newtag->name = tag;
2143 newtag->color = tagcolor;
2144 tags = ucx_list_append(tags, newtag);
2145 store_tags = TRUE;
2146 }
2147 } else {
2148 if(tags) {
2149 tags = ucx_list_remove(tags, x);
2150 }
2151 store_tags = TRUE;
2152 }
2153 } else {
2154 if(args->argc == 2) {
2155 char *tags_str = args->argv[1];
2156 tags = parse_csv_taglist(tags_str, strlen(tags_str));
2157 // TODO: read from stdin if tags_str is "-"
2158 }
2159 }
2160
2161 if(store_tags) {
2162 if(sync_store_tags_local(file.dir, NULL, path, tags)) {
2163 fprintf(stderr, "Cannot store tags\n");
2164 }
2165 if(localres) {
2166 localres->tags_updated = TRUE;
2167 }
2168 }
2169
2170 // store db
2171 if(store_db(db, file.dir->database)) {
2172 fprintf(stderr, "Cannot store sync db\n");
2173 ret = -2;
2174 }
2175
2176 free(file.path);
2177 return ret;
2178 }
2179
2180 static int isfileindir(SyncDirectory *dir, const char *path, SyncFile *f) {
2181 char *fullpath;
2182 if(path[0] != '/') {
2183 size_t wdlen = 1024;
2184 char *wd = malloc(1024);
2185 while(!getcwd(wd, wdlen)) {
2186 if(errno == ERANGE) {
2187 wdlen *= 2;
2188 wd = realloc(wd, wdlen);
2189 } else {
2190 free(wd);
2191 return 0;
2192 }
2193 }
2194
2195 fullpath = util_concat_path(wd, path);
2196 } else {
2197 fullpath = strdup(path);
2198 }
2199
2200 // TODO: normalize path
2201
2202 if(!sstrprefix(sstr((char*)fullpath), sstr(dir->path))) {
2203 free(fullpath);
2204 return 0;
2205 }
2206
2207 // TODO: check filter
2208
2209 f->dir = dir;
2210 f->path = util_concat_path("/", fullpath + strlen(dir->path));
2211
2212 free(fullpath);
2213 return 1;
2214 }
2215
2216 int sync_get_file(CmdArgs *args, const char *path, const char *dir, SyncFile *f) {
2217 struct stat s;
2218 if(stat(path, &s)) {
2219 switch(errno) {
2220 case EACCES: return 2;
2221 case ENOENT: return 1;
2222 default: return 3;
2223 }
2224 }
2225
2226 char *sdir = cmd_getoption(args, "syncdir");
2227
2228 if(sdir) {
2229 SyncDirectory *dir = scfg_get_dir(sdir);
2230 if(!dir) {
2231 return 6;
2232 }
2233 if(!isfileindir(dir, path, f)) {
2234 return 4;
2235 }
2236 } else {
2237 SyncDirectory *target = NULL;
2238
2239 UcxMapIterator i = scfg_directory_iterator();
2240 UcxKey k;
2241 SyncDirectory *dir;
2242 UCX_MAP_FOREACH(key, dir, i) {
2243 if(isfileindir(dir, path, f)) {
2244 if(target) {
2245 return 5;
2246 } else {
2247 target = dir;
2248 }
2249 }
2250 }
2251
2252 if(!target) {
2253 return 4;
2254 }
2255 }
2256
2257 return 0;
2258 }
2259
2044 2260
2045 int cmd_add_directory(CmdArgs *args) { 2261 int cmd_add_directory(CmdArgs *args) {
2046 if(!get_repositories()) { 2262 if(!get_repositories()) {
2047 fprintf(stderr, "No repositories available. Run 'dav add-repository' first.\n"); 2263 fprintf(stderr, "No repositories available. Run 'dav add-repository' first.\n");
2048 fprintf(stderr, "Abort\n"); 2264 fprintf(stderr, "Abort\n");

mercurial