summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-07-19 16:04:48 +0000
committerLennart Poettering <lennart@poettering.net>2004-07-19 16:04:48 +0000
commita952692561d8b1c59d4a384812b52d7225953bb3 (patch)
tree8a171edfa50639f6a79af39ceeab332dac56047d
parentebf3b3ad1795c877c4164b46aab1397237210417 (diff)
add support for --forget
git-svn-id: file:///home/lennart/svn/public/syrep/trunk@58 07ea20a6-d2c5-0310-9e02-9ef735347d72
-rw-r--r--doc/todo.txt2
-rw-r--r--src/Makefile.am3
-rw-r--r--src/dbstruct.h1
-rw-r--r--src/dbutil.c7
-rw-r--r--src/forget.c192
-rw-r--r--src/forget.h28
-rw-r--r--src/history.c2
-rw-r--r--src/package.c2
-rw-r--r--src/syrep.c151
-rw-r--r--src/syrep.ggo3
-rw-r--r--src/update.c4
-rw-r--r--src/update.h4
12 files changed, 344 insertions, 55 deletions
diff --git a/doc/todo.txt b/doc/todo.txt
index 762843c..30ab367 100644
--- a/doc/todo.txt
+++ b/doc/todo.txt
@@ -31,7 +31,7 @@ post-0.1:
- some more asserts
- PATH_MAX or PATH_MAX+1? DONE
- add --always-copy DONE
-- add --forget
+- add --forget DONE
- valgrind
$Id$
diff --git a/src/Makefile.am b/src/Makefile.am
index de07fbc..d829809 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,7 +38,8 @@ syrep_SOURCES = cache.c cache.h \
cleanup.c cleanup.h \
cmdline.c cmdline.h \
svn-revision.h \
- dbstruct.h
+ dbstruct.h \
+ forget.c forget.h
EXTRA_DIST = syrep.ggo
MAINTAINERCLEANFILES =
diff --git a/src/dbstruct.h b/src/dbstruct.h
index 842e33d..d0a7a85 100644
--- a/src/dbstruct.h
+++ b/src/dbstruct.h
@@ -68,6 +68,7 @@ struct syrep_name {
* syrep_id :: syrep_meta => id_meta
* syrep_md :: syrep_nrecno => md_nrecno (DUP)
* syrep_nrecno :: syrep_md => nrecno_md (DUP)
+ *
* syrep_nrecno :: syrep_md => nrecno_lastmd
* syrep_md :: syrep_nrecno => md_lastnrecno
*
diff --git a/src/dbutil.c b/src/dbutil.c
index cfa3150..09c092d 100644
--- a/src/dbutil.c
+++ b/src/dbutil.c
@@ -268,8 +268,6 @@ int get_nrecno_by_name(struct syrep_db_context *c, const struct syrep_name *rnam
struct syrep_nrecno nrecno;
struct syrep_name name;
-/* struct syrep_nhash *foo1; */
-/* struct syrep_nrecno *foo2; */
int f;
if (ret) {
@@ -289,11 +287,6 @@ int get_nrecno_by_name(struct syrep_db_context *c, const struct syrep_name *rnam
goto finish;
}
-/* foo1 = key.data; */
-/* foo2 = data.data; */
-
-/* fprintf(stderr, "cursor: %u ?= %u, %u\n", nhash.hash, foo1->hash, foo2->recno); */
-
memcpy(&nrecno, data.data, sizeof(nrecno));
if ((f = get_name_by_nrecno(c, &nrecno, &name)) < 0)
diff --git a/src/forget.c b/src/forget.c
new file mode 100644
index 0000000..befcf3f
--- /dev/null
+++ b/src/forget.c
@@ -0,0 +1,192 @@
+/* $Id$ */
+
+/***
+ This file is part of syrep.
+
+ syrep is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ syrep is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with syrep; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "forget.h"
+#include "dbstruct.h"
+#include "util.h"
+#include "dbutil.h"
+#include "update.h"
+
+static int copy_entries(struct syrep_db_context *c, struct syrep_db_context *target, uint32_t limit) {
+ int ret, r = -1;
+ DBT key, data;
+ DBC *cursor = NULL;
+ unsigned n = 0, t = 0;
+ assert(c);
+
+ if ((ret = c->db_id_meta->cursor(c->db_id_meta, NULL, &cursor, 0)) != 0) {
+ c->db_id_meta->err(c->db_id_meta, ret, "id_meta");
+ goto finish;
+ }
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ while ((ret = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) {
+ struct syrep_id *id = (struct syrep_id*) key.data;
+ struct syrep_meta *meta = (struct syrep_meta*) data.data;
+ struct syrep_name name;
+ uint32_t ts;
+
+ if (interrupted) {
+ fprintf(stderr, "Canceled.\n");
+ goto finish;
+ }
+
+ rotdash();
+ t++;
+
+ if ((ts = get_version_timestamp(c, meta->last_seen)) == (uint32_t) -1)
+ goto finish;
+
+ if (ts < limit)
+ continue;
+
+ n++;
+
+ /* copy it */
+ if (get_name_by_nrecno(c, &id->nrecno, &name) < 0)
+ goto finish;
+
+ if (write_entry(target, &name, &id->md, meta) < 0)
+ goto finish;
+ }
+
+ if (ret != DB_NOTFOUND) {
+ c->db_version_timestamp->err(c->db_id_meta, ret, "id_meta::c_get");
+ goto finish;
+ }
+
+ if (args.verbose_flag)
+ fprintf(stderr, "Removed %u of %u file entries.\n", t-n, t);
+
+ r = 0;
+
+finish:
+ if (cursor)
+ cursor->c_close(cursor);
+
+ return r;
+}
+
+
+static int copy_history(struct syrep_db_context *c, struct syrep_db_context *target, uint32_t limit) {
+ int ret, r = -1;
+ DBT key, data;
+ DBC *cursor = NULL;
+ unsigned n = 0, t = 0;
+ assert(c);
+
+ if ((ret = c->db_version_timestamp->cursor(c->db_version_timestamp, NULL, &cursor, 0)) != 0) {
+ c->db_version_timestamp->err(c->db_version_timestamp, ret, "version_timestamp");
+ goto finish;
+ }
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ while ((ret = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) {
+ struct syrep_timestamp *timestamp = (struct syrep_timestamp*) data.data;
+ assert(timestamp);
+
+ if (interrupted) {
+ fprintf(stderr, "Canceled.\n");
+ goto finish;
+ }
+
+ rotdash();
+ t++;
+
+ if (timestamp->t < limit)
+ continue;
+
+ n++;
+
+ /* copy it */
+
+ if ((ret = target->db_version_timestamp->put(target->db_version_timestamp, NULL, &key, &data, 0)) != 0) {
+ c->db_version_timestamp->err(c->db_version_timestamp, ret, "version_timestamp::put");
+ goto finish;
+ }
+
+
+ }
+
+ if (ret != DB_NOTFOUND) {
+ c->db_version_timestamp->err(c->db_version_timestamp, ret, "version_timestamp::c_get");
+ goto finish;
+ }
+
+ if (args.verbose_flag)
+ fprintf(stderr, "Removed %u of %u history entries.\n", t-n, t);
+
+ r = 0;
+
+finish:
+ if (cursor)
+ cursor->c_close(cursor);
+
+ return r;
+}
+
+int forget(struct syrep_db_context *c, struct syrep_db_context *target) {
+ uint32_t t;
+ time_t now, limit;
+
+ assert(c && target);
+
+ if (args.remember_arg < 0) {
+ fprintf(stderr, "ERROR: The remembrance time has to be greater or equal to 0\n");
+ return -1;
+ }
+
+ t = args.remember_arg*24*60*60;
+ time(&now);
+ limit = t > now ? 0 : now-t;
+
+ if (args.verbose_flag) {
+ fprintf(stderr, "Current time is %s", ctime(&now));
+ fprintf(stderr, "Forgetting all entries prior to %s", ctime(&limit));
+ }
+
+ if (copy_entries(c, target, (uint32_t) limit) < 0)
+ return -1;
+
+ if (copy_history(c, target, (uint32_t) limit) < 0)
+ return -1;
+
+ target->timestamp = c->timestamp;
+ target->version = c->version;
+ free(target->origin);
+ target->origin = strdup(c->origin);
+
+ target->modified = 1;
+
+ return 0;
+}
diff --git a/src/forget.h b/src/forget.h
new file mode 100644
index 0000000..c9716b2
--- /dev/null
+++ b/src/forget.h
@@ -0,0 +1,28 @@
+#ifndef fooforgethfoo
+#define fooforgethfoo
+
+/* $Id$ */
+
+/***
+ This file is part of syrep.
+
+ syrep is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ syrep is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with syrep; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***/
+
+#include "context.h"
+
+int forget(struct syrep_db_context *c, struct syrep_db_context *target);
+
+#endif
diff --git a/src/history.c b/src/history.c
index ff8532e..7c6a8a2 100644
--- a/src/history.c
+++ b/src/history.c
@@ -53,7 +53,7 @@ int history(struct syrep_db_context *c) {
assert(version && timestamp);
- fprintf(stderr, "%4u %10u %s", version->v, timestamp->t, ctime((time_t*) (&timestamp->t)));
+ printf("%4u %10u %s", version->v, timestamp->t, ctime((time_t*) (&timestamp->t)));
}
if (ret != DB_NOTFOUND) {
diff --git a/src/package.c b/src/package.c
index c2841ad..ef37c35 100644
--- a/src/package.c
+++ b/src/package.c
@@ -549,8 +549,6 @@ struct package* package_open(const char *fn, int force) {
}
if (fn) {
-
-
if (!strcmp(fn, "-"))
p->read_fd = STDIN_FILENO;
else if ((p->read_fd = open(fn, O_RDONLY)) < 0) {
diff --git a/src/syrep.c b/src/syrep.c
index 266082f..5ac60bd 100644
--- a/src/syrep.c
+++ b/src/syrep.c
@@ -56,6 +56,7 @@
#include "extract.h"
#include "makepatch.h"
#include "cleanup.h"
+#include "forget.h"
#include "svn-revision.h"
@@ -293,7 +294,6 @@ static int do_foreach(int (*func) (struct syrep_db_context *c), int m) {
}
}
-
if (func(c) < 0)
goto finish;
@@ -304,7 +304,6 @@ static int do_foreach(int (*func) (struct syrep_db_context *c), int m) {
}
}
-
if (args.inputs_num > 1 && i < args.inputs_num-1)
fprintf(stderr, "\n");
@@ -452,7 +451,67 @@ static int do_cleanup(void) {
finish:
return r;
+}
+
+static int do_forget(void) {
+ char *path = NULL;
+ int r = 1, i;
+ struct syrep_db_context *c = NULL, *target = 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 (args.local_temp_flag && isdirectory(args.inputs[i]) >= 1) {
+ const char *p = get_attached_filename(args.inputs[i], SYREP_TEMPDIR);
+ mkdir(p, 0777);
+ setenv("TMPDIR", p, 1);
+ }
+
+ if (!(path = strdup(get_snapshot_filename(args.inputs[i], SYREP_SNAPSHOTFILENAME))))
+ goto finish;
+
+ if (!(c = db_context_open(path, 0)))
+ goto finish;
+
+ if (!(target = db_context_open(NULL, 1)))
+ goto finish;
+
+ if (args.inputs_num > 1)
+ fprintf(stderr, "*** %s ***\n", path);
+
+ if (forget(c, target) < 0)
+ goto finish;
+
+ if (args.inputs_num > 1 && i < args.inputs_num-1)
+ fprintf(stderr, "\n");
+
+ db_context_free(c);
+
+ if (db_context_save(target, path) < 0)
+ goto finish;
+
+ db_context_free(target);
+ c = NULL;
+ target = NULL;
+
+ free(path);
+ path = NULL;
+ }
+
+ r = 0;
+
+finish:
+ if (c)
+ db_context_free(c);
+
+ if (target)
+ db_context_free(target);
+
+ if (path)
+ free(path);
+
+ return r;
}
static void sigint(int s) {
@@ -477,58 +536,66 @@ static int help(const char *argv0) {
"Usage: %s [options...] <command> [arguments...]\n\n"
"General options:\n"
- " -v --verbose Enable verbose operation\n"
- " -T --local-temp Use temporary directory inside repository\n"
- " --ignore-origin Don't warn if snapshot not local in update, merge, makepatch\n"
- " -z --compress Compress snapshots or patches\n"
- " -p --progress Show progress\n\n"
+ " -v --verbose Enable verbose operation\n"
+ " -T --local-temp Use temporary directory inside repository\n"
+ " --ignore-origin Don't warn if snapshot not local in update, merge, makepatch\n"
+ " -z --compress Compress snapshots or patches\n"
+ " -p --progress Show progress\n\n"
"General commands:\n"
- " -h --help Print help and exit\n"
- " -V --version Print version and exit\n\n"
+ " -h --help Print help and exit\n"
+ " -V --version Print version and exit\n\n"
"Specific commands:\n"
- " --list SNAPSHOT List a repository snapshot\n"
- " --show-deleted Show deleted entries of repository snapshot\n"
- " --show-by-md Show files by message digests\n"
- " --show-times Show first and last seen times\n"
- " --sort Sort chronologically\n\n"
+ " --list SNAPSHOT List a repository snapshot\n"
+ " --show-deleted Show deleted entries of repository snapshot\n"
+ " --show-by-md Show files by message digests\n"
+ " --show-times Show first and last seen times\n"
+ " --sort Sort chronologically\n\n"
- " --info SNAPSHOT Show information about a repository or snapshot\n\n"
+ " --info SNAPSHOT Show information about a repository or snapshot\n\n"
- " --history SNAPSHOT Show history of a repository or snapshot\n\n"
+ " --history SNAPSHOT Show history of a repository or snapshot\n\n"
- " --dump SNAPSHOT Show a structure dump of a repository or snapshot\n\n"
+ " --dump SNAPSHOT Show a structure dump of a repository or snapshot\n\n"
- " --update DIRECTORY Update (or create) a repository snapshot\n"
- " -SSTRING --snapshot=STRING Use the specified snapshot file instead of the one contained in the repository\n"
- " -CSTRING --cache=STRING Use the specified cache file instead of the one contained in the repository\n"
- " --no-cache Don't use a message digest cache\n"
- " --no-purge Don't purge obsolete entries from cache after update run\n"
- " --ro-cache Use read only cache\n\n"
+ " --update DIRECTORY Update (or create) a repository snapshot\n"
+ " -SSTRING --snapshot=STRING Use a different snapshot file than the one contained\n"
+ " in the repository\n"
+ " -CSTRING --cache=STRING Use a different cache file than the one contained in\n"
+ " the repository\n"
+ " --no-cache Don't use a message digest cache\n"
+ " --no-purge Don't purge obsolete entries from cache after update run\n"
+ " --ro-cache Use read only cache\n\n"
- " --diff SNAPSHOT SNAPSHOT Show difference between two repositories or snapshots\n\n"
+ " --diff SNAPSHOT SNAPSHOT Show difference between two repositories or snapshots\n"
+ " --sizes -s Show sizes for files to copy (works only with repositories)\n"
+ " --human-readable -H Show sizes in human readable from\n"
- " --merge SNAPSHOT DIRECTORY Merge a snapshot into a repository (perform deletes, renames only)\n"
- " --merge PATCH DIRECTORY Merge a patch into a repository\n"
- " --merge DIRECTORY DIRECTORY Merge a repository into a repository\n"
- " -q --question Ask a question before each action\n"
- " -P --prune-empty Prune empty directories\n"
- " --keep-trash Don't empty trash\n"
- " --check-md Check message digest of files prior to deletion or replacement\n"
- " --always-copy Always copy instead of hard link\n\n"
+ " --merge SNAPSHOT DIRECTORY Merge a snapshot into a repository (perform deletes,\n"
+ " renames only)\n"
+ " --merge PATCH DIRECTORY Merge a patch into a repository\n"
+ " --merge DIRECTORY DIRECTORY Merge a repository into a repository\n"
+ " -q --question Ask a question before each action\n"
+ " -P --prune-empty Prune empty directories\n"
+ " --keep-trash Don't empty trash\n"
+ " --check-md Check message digest of files prior to deletion or replacement\n"
+ " --always-copy Always copy instead of hard link\n\n"
- " --makepatch DIRECTORY SNAPSHOT Make a patch against the specified repository\n"
- " -oSTRING --output-file=STRING Write output to specified file instead of STDOUT\n"
- " --include-all Include files in patch which do exist on the other side under a different name\n\n"
+ " --makepatch DIRECTORY SNAPSHOT Make a patch against the specified repository\n"
+ " -oSTRING --output-file=STRING Write output to specified file instead of STDOUT\n"
+ " --include-all Include files in patch which do exist on the other side under a \n"
+ " different name\n\n"
- " --extract SNAPSHOT Extract the contents of a snapshot or patch\n"
- " -DSTRING --output-directory=STRING Write output to specified directory\n\n"
+ " --extract SNAPSHOT Extract the contents of a snapshot or patch\n"
+ " -DSTRING --output-directory=STRING Write output to specified directory\n\n"
- " --cleanup DIRECTORY Remove syrep info from repository\n"
- " -lINT --cleanup-level=INT 1 - just remove temporary data and trash (default)\n"
- " 2 - remove MD cache as well\n"
- " 3 - remove all syrep data\n",
+ " --cleanup DIRECTORY Remove syrep info from repository\n"
+ " -lINT --cleanup-level=INT 1 - just remove temporary data and trash (default)\n"
+ " 2 - remove MD cache as well\n"
+ " 3 - remove all syrep data\n\n"
+ " --forget SNAPSHOT Repackage snapshot dropping outdated information\n"
+ " --remember DAYS Information of how many days should be kept? (defaults to 180)\n",
argv0, argv0);
return 0;
@@ -599,6 +666,8 @@ int main(int argc, char *argv[]) {
return do_makepatch();
else if (args.cleanup_flag)
return do_cleanup();
+ else if (args.forget_flag)
+ return do_forget();
help(bn);
diff --git a/src/syrep.ggo b/src/syrep.ggo
index d2a7bb1..53c60ae 100644
--- a/src/syrep.ggo
+++ b/src/syrep.ggo
@@ -62,3 +62,6 @@ option "extract" - "Extract the context of a snapshot or patch" flag off
option "cleanup" - "Remove syrep info from repository" flag off
option "cleanup-level" l "cleanup: 1 - just remove temporary data and trash (default); 2 - remove MD cache as well; 3 - remove all syrep data" int default="1" no
+
+option "forget" - "Forget old snapshot entries" flag off
+ option "remember" R "forget: information of how many days to remeber" int default="180" no
diff --git a/src/update.c b/src/update.c
index 6fc2d06..4fe6758 100644
--- a/src/update.c
+++ b/src/update.c
@@ -59,7 +59,7 @@ static int dbput(DB* db, const void *k, int klen, const void*d, int dlen, int f)
return 1;
}
-static int write_entry(struct syrep_db_context *c, const struct syrep_name *name, const struct syrep_md *md, const struct syrep_meta *meta) {
+int write_entry(struct syrep_db_context *c, const struct syrep_name *name, const struct syrep_md *md, const struct syrep_meta *meta) {
struct syrep_id id;
struct syrep_nrecno nrecno;
int f;
@@ -95,7 +95,7 @@ static int write_entry(struct syrep_db_context *c, const struct syrep_name *name
if ((f = dbput(c->db_nrecno_lastmd, &nrecno, sizeof(struct syrep_nrecno), md, sizeof(struct syrep_md), 0)) < 0)
return -1;
- //fprintf(stderr, "Insert: %s %i\n", name->path, f);
+ /*fprintf(stderr, "Insert: %s %i\n", name->path, f);*/
c->modified = 1;
return 0;
diff --git a/src/update.h b/src/update.h
index 81e26d0..57040f5 100644
--- a/src/update.h
+++ b/src/update.h
@@ -23,7 +23,11 @@
#include "context.h"
#include "cache.h"
+#include "dbstruct.h"
int update(struct syrep_db_context *c, struct syrep_md_cache *cache);
+/* This is exported solely for usage in forget.c */
+int write_entry(struct syrep_db_context *c, const struct syrep_name *name, const struct syrep_md *md, const struct syrep_meta *meta);
+
#endif