git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 10/24] backup-log: add cat command

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Dec 9, 2018, 10:44 UTC
Message-ID
<20181209104419.12639-11-pclouds@gmail.com>
In-Reply-To
<20181209104419.12639-1-pclouds@gmail.com>

This command introduces a new concept, "change id". This is similar to "n" in reflog sha-1 extended syntax @{n}. I'm trying to group changes of the same second together, and this timestamp becomes "change id", so you view roughly a snapshot of changes. Of course it's not 100% accurate. But it works most of the time and it keeps log update low.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/backup-log.c  | 83 +++++++++++++++++++++++++++++++++++++++++++
 t/t2080-backup-log.sh | 17 +++++++++
 2 files changed, 100 insertions(+)
diff --git a/builtin/backup-log.c b/builtin/backup-log.c
index 75a02c8878..b370ff9d27 100644
--- a/builtin/backup-log.c
+++ b/builtin/backup-log.c
@@ -1,10 +1,13 @@
 #include "cache.h"
 #include "builtin.h"
 #include "backup-log.h"
+#include "dir.h"
+#include "object-store.h"
 #include "parse-options.h"
 
 static char const * const backup_log_usage[] = {
 	N_("git backup-log [--path=<path> | --id=<id>] update <path> <old-hash> <new-hash>"),
+	N_("git backup-log [--path=<path> | --id=<id>] cat [<options>] <change-id> <path>"),
 	NULL
 };
 
@@ -34,6 +37,84 @@ static int update(int argc, const char **argv,
 	return ret;
 }
 
+struct cat_options {
+	timestamp_t id;
+	char *path;
+	int before;
+	int show_hash;
+};
+
+static int cat_parse(struct strbuf *line, void *data)
+{
+	struct cat_options *opts = data;
+	struct bkl_entry entry;
+	struct object_id *oid;
+	void *buf;
+	unsigned long size;
+	enum object_type type;
+
+	if (bkl_parse_entry(line, &entry))
+		return -1;
+
+	if (entry.timestamp < opts->id)
+		return 2;
+
+	if (entry.timestamp != opts->id ||
+	    fspathcmp(entry.path, opts->path))
+		return 0;
+
+	if (opts->before)
+		oid = &entry.old_oid;
+	else
+		oid = &entry.new_oid;
+
+	if (opts->show_hash) {
+		puts(oid_to_hex(oid));
+		return 1;
+	}
+
+	if (is_null_oid(oid))
+		return 1;	/* treat null oid like empty blob */
+
+	buf = read_object_file(oid, &type, &size);
+	if (!buf)
+		die(_("object not found: %s"), oid_to_hex(oid));
+	if (type != OBJ_BLOB)
+		die(_("not a blob: %s"), oid_to_hex(oid));
+
+	write_in_full(1, buf, size);
+	free(buf);
+
+	return 1;
+}
+
+static int cat(int argc, const char **argv,
+		const char *prefix, const char *log_path)
+{
+	struct cat_options opts;
+	struct option options[] = {
+		OPT_BOOL(0, "before", &opts.before, N_("select the version before the update")),
+		OPT_BOOL(0, "hash", &opts.show_hash, N_("show the hash instead of the content")),
+		OPT_END()
+	};
+	char *end = NULL;
+	int ret;
+
+	memset(&opts, 0, sizeof(opts));
+	argc = parse_options(argc, argv, prefix, options, backup_log_usage, 0);
+	if (argc != 2)
+		usage_with_options(backup_log_usage, options);
+	opts.id = strtol(argv[0], &end, 10);
+	if (!end || *end)
+		die(_("not a valid change id: %s"), argv[0]);
+	opts.path = prefix_path(prefix, prefix ? strlen(prefix) : 0, argv[1]);
+	setup_pager();
+	ret = bkl_parse_file_reverse(log_path, cat_parse, &opts);
+	if (ret < 0)
+		die(_("failed to parse '%s'"), log_path);
+	return ret - 1;
+}
+
 static char *log_id_to_path(const char *id)
 {
 	if (!strcmp(id, "index"))
@@ -73,6 +154,8 @@ int cmd_backup_log(int argc, const char **argv, const char *prefix)
 
 	if (!strcmp(argv[0], "update"))
 		return update(argc, argv, prefix, log_path);
+	else if (!strcmp(argv[0], "cat"))
+		return cat(argc, argv, prefix, log_path);
 	else
 		die(_("unknown subcommand: %s"), argv[0]);
 
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
index 8d1c8c5935..9c004c9727 100755
--- a/t/t2080-backup-log.sh
+++ b/t/t2080-backup-log.sh
@@ -88,4 +88,21 @@ test_expect_success 'apply --cached writes backup log' '
 	test_cmp expected .git/index.bkl
 '
 
+test_expect_success 'backup-log cat' '
+	OLD=$(git rev-parse :./initial.t) &&
+	echo update >>initial.t &&
+	test_tick &&
+	git -c core.backupLog=true add initial.t &&
+	NEW=$(git rev-parse :./initial.t) &&
+	git backup-log --id=index cat --before --hash $test_tick initial.t >actual &&
+	echo $OLD >expected &&
+	test_cmp expected actual &&
+	git backup-log --id=index cat --hash $test_tick initial.t >actual &&
+	echo $NEW >expected &&
+	test_cmp expected actual &&
+	git backup-log --id=index cat $test_tick initial.t >actual &&
+	git cat-file blob $NEW >expected &&
+	test_cmp expected actual
+'
+
 test_done
-- 
2.20.0.rc2.486.g9832c05c3d
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 12 of 25 in “Add backup log”
  1. 00/24 Add backup logNguyễn Thái Ngọc Duy, Dec 9, 2018
  2. 01/24 doc: introduce new "backup log" conceptNguyễn Thái Ngọc Duy, Dec 9, 2018
  3. 02/24 backup-log: add "update" subcommandNguyễn Thái Ngọc Duy, Dec 9, 2018
  4. 03/24 read-cache.c: new flag for add_index_entry() to write to backup logNguyễn Thái Ngọc Duy, Dec 9, 2018
  5. 04/24 add: support backup logNguyễn Thái Ngọc Duy, Dec 9, 2018
  6. 05/24 update-index: support backup log with --keep-backupNguyễn Thái Ngọc Duy, Dec 9, 2018
  7. 08/24 add--interactive: support backup logNguyễn Thái Ngọc Duy, Dec 9, 2018
  8. 06/24 commit: support backup logNguyễn Thái Ngọc Duy, Dec 9, 2018
  9. 07/24 apply: support backup log with --keep-backupNguyễn Thái Ngọc Duy, Dec 9, 2018
  10. 09/24 backup-log.c: add API for walking backup logNguyễn Thái Ngọc Duy, Dec 9, 2018
  11. 11/24 backup-log: add diff commandNguyễn Thái Ngọc Duy, Dec 9, 2018
  12. 10/24 backup-log: add cat commandNguyễn Thái Ngọc Duy, Dec 9, 2018
  13. 12/24 backup-log: add log commandNguyễn Thái Ngọc Duy, Dec 9, 2018
  14. 17/24 config --edit: support backup logNguyễn Thái Ngọc Duy, Dec 9, 2018
  15. 18/24 refs: keep backup of deleted reflogNguyễn Thái Ngọc Duy, Dec 9, 2018
  16. 15/24 backup-log: keep all blob references aroundNguyễn Thái Ngọc Duy, Dec 9, 2018
  17. 19/24 unpack-trees.c: keep backup of ignored files being overwrittenNguyễn Thái Ngọc Duy, Dec 9, 2018
  18. 22/24 am: keep backup of overwritten files on --skip or --abortNguyễn Thái Ngọc Duy, Dec 9, 2018
  19. 21/24 checkout -f: keep backup of overwritten filesNguyễn Thái Ngọc Duy, Dec 9, 2018
  20. 14/24 gc: prune backup logsNguyễn Thái Ngọc Duy, Dec 9, 2018
  21. 23/24 rebase: keep backup of overwritten files on --skip or --abortNguyễn Thái Ngọc Duy, Dec 9, 2018
  22. 24/24 FIXMENguyễn Thái Ngọc Duy, Dec 9, 2018
  23. 20/24 reset --hard: keep backup of overwritten filesNguyễn Thái Ngọc Duy, Dec 9, 2018
  24. 16/24 sha1-file.c: let index_path() accept NULL istateNguyễn Thái Ngọc Duy, Dec 9, 2018
  25. 13/24 backup-log: add prune commandNguyễn Thái Ngọc Duy, Dec 9, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.