diff options
Diffstat (limited to 'src/syrep.c')
-rw-r--r-- | src/syrep.c | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/src/syrep.c b/src/syrep.c new file mode 100644 index 0000000..07bbe37 --- /dev/null +++ b/src/syrep.c @@ -0,0 +1,301 @@ +#include <stdint.h> +#include <limits.h> +#include <db.h> +#include <assert.h> +#include <malloc.h> +#include <string.h> +#include <sys/types.h> +#include <dirent.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +#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" + +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)) { + 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++) { + + 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 (func(c) < 0) + goto finish; + + 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); + else if (args.info_flag) + return do_foreach(info); + else if (args.history_flag) + return do_foreach(history); + 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); + + cmdline_parser_print_help(); + + return 1; +} |