#include #include #include #include #include #include #include #include #include #include #include #include #include #include "md5util.h" #include "md5.h" #include "context.h" #include "cache.h" #include "update.h" #include "list.h" #include "diff.h" #include "util.h" #include "cmdline.h" #include "syrep.h" #include "merge.h" #include "info.h" #include "history.h" #include "dump.h" #include "extract.h" struct gengetopt_args_info args; int do_diff(void) { struct syrep_db_context *c1 = NULL, *c2 = NULL; char *path1 = NULL, *path2 = NULL; DB *ddb = NULL; int r = 1; if (args.inputs_num != 2) { fprintf(stderr, "ERROR: Need exactly two repository snapshots for diff command\n"); goto finish; } if (!(path1 = strdup(get_attached_filename(args.inputs[0], SYREP_SNAPSHOTFILENAME)))) goto finish; if (!(path2 = strdup(get_attached_filename(args.inputs[1], SYREP_SNAPSHOTFILENAME)))) goto finish; if (!strcmp(path1, path2)) { fprintf(stderr, "ERROR: diff command requires two distinct snapshots as arguments\n"); goto finish; } if (!(c1 = db_context_open(path1))) goto finish; if (!(c2 = db_context_open(path2))) goto finish; if (!(ddb = make_diff(c1, c2))) goto finish; if (list_diff(c1, c2, ddb) < 0) goto finish; r = 0; finish: if (c1) db_context_free(c1); if (c2) db_context_free(c2); if (ddb) ddb->close(ddb, 0); if (path1) free(path1); if (path2) free(path2); return r; } int do_merge(void) { struct syrep_db_context *c1 = NULL, *c2 = NULL; char *path1 = NULL, *path2 = NULL; int r = 1; if (args.inputs_num != 2) { fprintf(stderr, "ERROR: Need exactly one repository snapshot and one repository for merge command\n"); goto finish; } if (isdirectory(args.inputs[1]) <= 0) { fprintf(stderr, "ERROR: %s is not a directory\n", args.inputs[1]); goto finish; } if (!(path1 = strdup(get_attached_filename(args.inputs[0], SYREP_SNAPSHOTFILENAME)))) goto finish; if (!(path2 = strdup(get_attached_filename(args.inputs[1], SYREP_SNAPSHOTFILENAME)))) goto finish; if (!strcmp(path1, path2)) { fprintf(stderr, "ERROR: diff command requires two distinct snapshots as arguments\n"); goto finish; } if (!(c1 = db_context_open(path1))) goto finish; if (!(c2 = db_context_open(path2))) goto finish; if (merge_snapshot(c1, c2, args.inputs[1]) < 0) goto finish; r = 0; finish: if (c1) db_context_free(c1); if (c2) db_context_free(c2); if (path1) free(path1); if (path2) free(path2); return r; } int do_foreach(int (*func) (struct syrep_db_context *c), int m) { char *path = NULL; int r = 1, i; struct syrep_db_context *c = NULL; if (args.inputs_num < 1) fprintf(stderr, "WARNING: No repository or snapshot to specified!\n"); for (i = 0; i < args.inputs_num; i++) { static char saved_cwd[PATH_MAX]; if (!(path = strdup(get_attached_filename(args.inputs[i], SYREP_SNAPSHOTFILENAME)))) goto finish; if (!(c = db_context_open(path))) goto finish; if (args.inputs_num > 1) fprintf(stderr, "*** %s ***\n", path); if (m && args.output_directory_given) { if (getcwd(saved_cwd, sizeof(saved_cwd)) < 0) { fprintf(stderr, "getcwd(): %s\n", strerror(errno)); return -1; } mkdir(args.output_directory_arg, 0777); if (chdir(args.output_directory_arg) < 0) { fprintf(stderr, "Failed to chdir() to directory %s: %s\n", args.output_directory_arg, strerror(errno)); return -1; } } if (func(c) < 0) goto finish; if (m && args.output_directory_given) { if (chdir(saved_cwd) < 0) { fprintf(stderr, "Failed to chdir() back to directory %s: %s\n", saved_cwd, strerror(errno)); return -1; } } if (args.inputs_num > 1 && i < args.inputs_num-1) fprintf(stderr, "\n"); db_context_free(c); c = NULL; free(path); path = NULL; } r = 0; finish: if (c) db_context_free(c); if (path) free(path); return r; } int do_update(void) { char *path = NULL; int r = 1, i; struct syrep_db_context *c = NULL; struct syrep_md_cache *cache = NULL; if (args.inputs_num < 1) fprintf(stderr, "WARNING: No repository to update specified!\n"); if (args.snapshot_given && args.inputs_num != 1) { fprintf(stderr, "ERROR: If a snapshot file is specified only a single directory name is accepted!\n"); goto finish; } for (i = 0; i < args.inputs_num; i++) { static char saved_cwd[PATH_MAX]; if (isdirectory(args.inputs[i]) <= 0) { fprintf(stderr, "%s is not a directory\n", args.inputs[i]); return 1; } if (!(path = strdup(get_attached_filename(args.inputs[i], SYREP_SNAPSHOTFILENAME)))) goto finish; if (!(c = db_context_open(path))) { fprintf(stderr, "Initializing repository.\n"); if (!(c = db_context_open(NULL))) goto finish; } if (!args.no_cache_flag) { const char *p; if (args.cache_given) cache = md_cache_open(args.cache_arg, args.ro_cache_flag); else if ((p = get_attached_filename(args.inputs[i], SYREP_MDCACHEFILENAME))) cache = md_cache_open(p, args.ro_cache_flag); } if (getcwd(saved_cwd, sizeof(saved_cwd)) < 0) { fprintf(stderr, "getcwd(): %s\n", strerror(errno)); goto finish; } if (chdir(args.inputs[i]) < 0) { fprintf(stderr, "Failed to chdir() to directory %s: %s\n", args.inputs[i], strerror(errno)); goto finish; } if (update(c, cache) < 0) goto finish; if (chdir(saved_cwd) < 0) { fprintf(stderr, "Failed to chdir() back to directory %s: %s\n", saved_cwd, strerror(errno)); goto finish; } if (db_context_save(c, path) < 0) goto finish; if (!args.no_purge_flag && cache) md_cache_vacuum(cache); db_context_free(c); c = NULL; free(path); path = NULL; if (cache) { md_cache_close(cache); cache = NULL; } } r = 0; finish: if (c) db_context_free(c); if (path) free(path); if (cache) md_cache_close(cache); return r; } int main(int argc, char *argv[]) { char *b; if ((b = strrchr(argv[0], '/'))) argv[0] = b+1; cmdline_parser(argc, argv, &args); if (args.list_flag) return do_foreach(list, 0); else if (args.info_flag) return do_foreach(info, 0); else if (args.history_flag) return do_foreach(history, 0); else if (args.diff_flag) return do_diff(); else if (args.update_flag) return do_update(); else if (args.merge_flag) return do_merge(); else if (args.dump_flag) return do_foreach(dump, 0); else if (args.extract_flag) return do_foreach(extract, 1); cmdline_parser_print_help(); return 1; }