summaryrefslogtreecommitdiffstats
path: root/src/syrep.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/syrep.c')
-rw-r--r--src/syrep.c301
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;
+}