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

[PATCH v3 08/17] builtin/pack-objects.c: --cruft without expiration

From
Taylor Blau <me@ttaylorr.com>
Date
Mar 3, 2022, 00:21 UTC
Message-ID
<22705e4887b5c9e3d7ef9ff1eadaabeeac0d57da.1646266835.git.me@ttaylorr.com>
In-Reply-To
<cover.1646266835.git.me@ttaylorr.com>

Teach `pack-objects` how to generate a cruft pack when no objects are dropped (i.e., `--cruft-expiration=never`). Later patches will teach `pack-objects` how to generate a cruft pack that prunes objects.

When generating a cruft pack which does not prune objects, we want to collect all unreachable objects into a single pack (noting and updating their mtimes as we accumulate them). Ordinary use will pass the result of a `git repack -A` as a kept pack, so when this patch says "kept pack", readers should think "reachable objects".

Generating a non-expiring cruft packs works as follows:
  - Callers provide a list of every pack they know about, and indicate
    which packs are about to be removed.
  - All packs which are going to be removed (we'll call these the
    redundant ones) are marked as kept in-core.
    Any packs the caller did not mention (but are known to the
    `pack-objects` process) are also marked as kept in-core. Packs not
    mentioned by the caller are assumed to be unknown to them, i.e.,
    they entered the repository after the caller decided which packs
    should be kept and which should be discarded.
    Since we do not want to include objects in these "unknown" packs
    (because we don't know which of their objects are or aren't
    reachable), these are also marked as kept in-core.
  - Then, we enumerate all objects in the repository, and add them to
    our packing list if they do not appear in an in-core kept pack.

This results in a new cruft pack which contains all known objects that aren't included in the kept packs. When the kept pack is the result of `git repack -A`, the resulting pack contains all unreachable objects.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
 Documentation/git-pack-objects.txt |  30 ++++
 builtin/pack-objects.c             | 201 +++++++++++++++++++++++++-
 object-file.c                      |   2 +-
 object-store.h                     |   2 +
 t/t5329-pack-objects-cruft.sh      | 218 +++++++++++++++++++++++++++++
 5 files changed, 448 insertions(+), 5 deletions(-)
 create mode 100755 t/t5329-pack-objects-cruft.sh
diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index f8344e1e5b..a9995a932c 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -13,6 +13,7 @@ SYNOPSIS
 	[--no-reuse-delta] [--delta-base-offset] [--non-empty]
 	[--local] [--incremental] [--window=<n>] [--depth=<n>]
 	[--revs [--unpacked | --all]] [--keep-pack=<pack-name>]
+	[--cruft] [--cruft-expiration=<time>]
 	[--stdout [--filter=<filter-spec>] | <base-name>]
 	[--shallow] [--keep-true-parents] [--[no-]sparse] < <object-list>
 
@@ -95,6 +96,35 @@ base-name::
 Incompatible with `--revs`, or options that imply `--revs` (such as
 `--all`), with the exception of `--unpacked`, which is compatible.
 
+--cruft::
+	Packs unreachable objects into a separate "cruft" pack, denoted
+	by the existence of a `.mtimes` file. Typically used by `git
+	repack --cruft`. Callers provide a list of pack names and
+	indicate which packs will remain in the repository, along with
+	which packs will be deleted (indicated by the `-` prefix). The
+	contents of the cruft pack are all objects not contained in the
+	surviving packs which have not exceeded the grace period (see
+	`--cruft-expiration` below), or which have exceeded the grace
+	period, but are reachable from an other object which hasn't.
++
+When the input lists a pack containing all reachable objects (and lists
+all other packs as pending deletion), the corresponding cruft pack will
+contain all unreachable objects (with mtime newer than the
+`--cruft-expiration`) along with any unreachable objects whose mtime is
+older than the `--cruft-expiration`, but are reachable from an
+unreachable object whose mtime is newer than the `--cruft-expiration`).
++
+Incompatible with `--unpack-unreachable`, `--keep-unreachable`,
+`--pack-loose-unreachable`, `--stdin-packs`, as well as any other
+options which imply `--revs`. Also incompatible with `--max-pack-size`;
+when this option is set, the maximum pack size is not inferred from
+`pack.packSizeLimit`.
+
+--cruft-expiration=<approxidate>::
+	If specified, objects are eliminated from the cruft pack if they
+	have an mtime older than `<approxidate>`. If unspecified (and
+	given `--cruft`), then no objects are eliminated.
+
 --window=<n>::
 --depth=<n>::
 	These two options affect how the objects contained in
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 3f08a3c63a..5ba4fc9c2c 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -36,6 +36,7 @@
 #include "trace2.h"
 #include "shallow.h"
 #include "promisor-remote.h"
+#include "pack-mtimes.h"
 
 /*
  * Objects we are going to pack are collected in the `to_pack` structure.
@@ -194,6 +195,8 @@ static int reuse_delta = 1, reuse_object = 1;
 static int keep_unreachable, unpack_unreachable, include_tag;
 static timestamp_t unpack_unreachable_expiration;
 static int pack_loose_unreachable;
+static int cruft;
+static timestamp_t cruft_expiration;
 static int local;
 static int have_non_local_packs;
 static int incremental;
@@ -1252,6 +1255,9 @@ static void write_pack_file(void)
 					&to_pack, written_list, nr_written);
 			}
 
+			if (cruft)
+				pack_idx_opts.flags |= WRITE_MTIMES;
+
 			stage_tmp_packfiles(&tmpname, pack_tmp_name,
 					    written_list, nr_written,
 					    &to_pack, &pack_idx_opts, hash,
@@ -3389,6 +3395,135 @@ static void read_packs_list_from_stdin(void)
 	string_list_clear(&exclude_packs, 0);
 }
 
+static void add_cruft_object_entry(const struct object_id *oid, enum object_type type,
+				   struct packed_git *pack, off_t offset,
+				   const char *name, uint32_t mtime)
+{
+	struct object_entry *entry;
+
+	display_progress(progress_state, ++nr_seen);
+
+	entry = packlist_find(&to_pack, oid);
+	if (entry) {
+		if (name) {
+			entry->hash = pack_name_hash(name);
+			entry->no_try_delta = no_try_delta(name);
+		}
+	} else {
+		if (!want_object_in_pack(oid, 0, &pack, &offset))
+			return;
+		if (!pack && type == OBJ_BLOB && !has_loose_object(oid)) {
+			/*
+			 * If a traversed tree has a missing blob then we want
+			 * to avoid adding that missing object to our pack.
+			 *
+			 * This only applies to missing blobs, not trees,
+			 * because the traversal needs to parse sub-trees but
+			 * not blobs.
+			 *
+			 * Note we only perform this check when we couldn't
+			 * already find the object in a pack, so we're really
+			 * limited to "ensure non-tip blobs which don't exist in
+			 * packs do exist via loose objects". Confused?
+			 */
+			return;
+		}
+
+		entry = create_object_entry(oid, type, pack_name_hash(name),
+					    0, name && no_try_delta(name),
+					    pack, offset);
+	}
+
+	if (mtime > oe_cruft_mtime(&to_pack, entry))
+		oe_set_cruft_mtime(&to_pack, entry, mtime);
+	return;
+}
+
+static void mark_pack_kept_in_core(struct string_list *packs, unsigned keep)
+{
+	struct string_list_item *item = NULL;
+	for_each_string_list_item(item, packs) {
+		struct packed_git *p = item->util;
+		if (!p)
+			die(_("could not find pack '%s'"), item->string);
+		p->pack_keep_in_core = keep;
+	}
+}
+
+static void add_unreachable_loose_objects(void);
+static void add_objects_in_unpacked_packs(void);
+
+static void enumerate_cruft_objects(void)
+{
+	if (progress)
+		progress_state = start_progress(_("Enumerating cruft objects"), 0);
+
+	add_objects_in_unpacked_packs();
+	add_unreachable_loose_objects();
+
+	stop_progress(&progress_state);
+}
+
+static void read_cruft_objects(void)
+{
+	struct strbuf buf = STRBUF_INIT;
+	struct string_list discard_packs = STRING_LIST_INIT_DUP;
+	struct string_list fresh_packs = STRING_LIST_INIT_DUP;
+	struct packed_git *p;
+
+	ignore_packed_keep_in_core = 1;
+
+	while (strbuf_getline(&buf, stdin) != EOF) {
+		if (!buf.len)
+			continue;
+
+		if (*buf.buf == '-')
+			string_list_append(&discard_packs, buf.buf + 1);
+		else
+			string_list_append(&fresh_packs, buf.buf);
+		strbuf_reset(&buf);
+	}
+
+	string_list_sort(&discard_packs);
+	string_list_sort(&fresh_packs);
+
+	for (p = get_all_packs(the_repository); p; p = p->next) {
+		const char *pack_name = pack_basename(p);
+		struct string_list_item *item;
+
+		item = string_list_lookup(&fresh_packs, pack_name);
+		if (!item)
+			item = string_list_lookup(&discard_packs, pack_name);
+
+		if (item) {
+			item->util = p;
+		} else {
+			/*
+			 * This pack wasn't mentioned in either the "fresh" or
+			 * "discard" list, so the caller didn't know about it.
+			 *
+			 * Mark it as kept so that its objects are ignored by
+			 * add_unseen_recent_objects_to_traversal(). We'll
+			 * unmark it before starting the traversal so it doesn't
+			 * halt the traversal early.
+			 */
+			p->pack_keep_in_core = 1;
+		}
+	}
+
+	mark_pack_kept_in_core(&fresh_packs, 1);
+	mark_pack_kept_in_core(&discard_packs, 0);
+
+	if (cruft_expiration)
+		die("--cruft-expiration not yet implemented");
+	else
+		enumerate_cruft_objects();
+
+	strbuf_release(&buf);
+	string_list_clear(&discard_packs, 0);
+	string_list_clear(&fresh_packs, 0);
+}
+
 static void read_object_list_from_stdin(void)
 {
 	char line[GIT_MAX_HEXSZ + 1 + PATH_MAX + 2];
@@ -3521,7 +3656,24 @@ static int add_object_in_unpacked_pack(const struct object_id *oid,
 				       uint32_t pos,
 				       void *_data)
 {
-	add_object_entry(oid, OBJ_NONE, "", 0);
+	if (cruft) {
+		off_t offset;
+		time_t mtime;
+
+		if (pack->is_cruft) {
+			if (load_pack_mtimes(pack) < 0)
+				die(_("could not load cruft pack .mtimes"));
+			mtime = nth_packed_mtime(pack, pos);
+		} else {
+			mtime = pack->mtime;
+		}
+		offset = nth_packed_object_offset(pack, pos);
+
+		add_cruft_object_entry(oid, OBJ_NONE, pack, offset,
+				       NULL, mtime);
+	} else {
+		add_object_entry(oid, OBJ_NONE, "", 0);
+	}
 	return 0;
 }
 
@@ -3545,7 +3697,19 @@ static int add_loose_object(const struct object_id *oid, const char *path,
 		return 0;
 	}
 
-	add_object_entry(oid, type, "", 0);
+	if (cruft) {
+		struct stat st;
+		if (stat(path, &st) < 0) {
+			if (errno == ENOENT)
+				return 0;
+			return error_errno("unable to stat %s", oid_to_hex(oid));
+		}
+
+		add_cruft_object_entry(oid, type, NULL, 0, NULL,
+				       st.st_mtime);
+	} else {
+		add_object_entry(oid, type, "", 0);
+	}
 	return 0;
 }
 
@@ -3864,6 +4028,20 @@ static int option_parse_unpack_unreachable(const struct option *opt,
 	return 0;
 }
 
+static int option_parse_cruft_expiration(const struct option *opt,
+					 const char *arg, int unset)
+{
+	if (unset) {
+		cruft = 0;
+		cruft_expiration = 0;
+	} else {
+		cruft = 1;
+		if (arg)
+			cruft_expiration = approxidate(arg);
+	}
+	return 0;
+}
+
 int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 {
 	int use_internal_rev_list = 0;
@@ -3936,6 +4114,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 		OPT_CALLBACK_F(0, "unpack-unreachable", NULL, N_("time"),
 		  N_("unpack unreachable objects newer than <time>"),
 		  PARSE_OPT_OPTARG, option_parse_unpack_unreachable),
+		OPT_BOOL(0, "cruft", &cruft, N_("create a cruft pack")),
+		OPT_CALLBACK_F(0, "cruft-expiration", NULL, N_("time"),
+		  N_("expire cruft objects older than <time>"),
+		  PARSE_OPT_OPTARG, option_parse_cruft_expiration),
 		OPT_BOOL(0, "sparse", &sparse,
 			 N_("use the sparse reachability algorithm")),
 		OPT_BOOL(0, "thin", &thin,
@@ -4062,7 +4244,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 
 	if (!HAVE_THREADS && delta_search_threads != 1)
 		warning(_("no threads support, ignoring --threads"));
-	if (!pack_to_stdout && !pack_size_limit)
+	if (!pack_to_stdout && !pack_size_limit && !cruft)
 		pack_size_limit = pack_size_limit_cfg;
 	if (pack_to_stdout && pack_size_limit)
 		die(_("--max-pack-size cannot be used to build a pack for transfer"));
@@ -4089,6 +4271,15 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 	if (stdin_packs && use_internal_rev_list)
 		die(_("cannot use internal rev list with --stdin-packs"));
 
+	if (cruft) {
+		if (use_internal_rev_list)
+			die(_("cannot use internal rev list with --cruft"));
+		if (stdin_packs)
+			die(_("cannot use --stdin-packs with --cruft"));
+		if (pack_size_limit)
+			die(_("cannot use --max-pack-size with --cruft"));
+	}
+
 	/*
 	 * "soft" reasons not to use bitmaps - for on-disk repack by default we want
 	 *
@@ -4145,7 +4336,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 			    the_repository);
 	prepare_packing_data(the_repository, &to_pack);
 
-	if (progress)
+	if (progress && !cruft)
 		progress_state = start_progress(_("Enumerating objects"), 0);
 	if (stdin_packs) {
 		/* avoids adding objects in excluded packs */
@@ -4153,6 +4344,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 		read_packs_list_from_stdin();
 		if (rev_list_unpacked)
 			add_unreachable_loose_objects();
+	} else if (cruft) {
+		read_cruft_objects();
 	} else if (!use_internal_rev_list) {
 		read_object_list_from_stdin();
 	} else {
diff --git a/object-file.c b/object-file.c
index 8be57f48de..e80da1368d 100644
--- a/object-file.c
+++ b/object-file.c
@@ -996,7 +996,7 @@ int has_loose_object_nonlocal(const struct object_id *oid)
 	return check_and_freshen_nonlocal(oid, 0);
 }
 
-static int has_loose_object(const struct object_id *oid)
+int has_loose_object(const struct object_id *oid)
 {
 	return check_and_freshen(oid, 0);
 }
diff --git a/object-store.h b/object-store.h
index 9b227661f2..6b025dc670 100644
--- a/object-store.h
+++ b/object-store.h
@@ -334,6 +334,8 @@ int repo_has_object_file_with_flags(struct repository *r,
  */
 int has_loose_object_nonlocal(const struct object_id *);
 
+int has_loose_object(const struct object_id *);
+
 void assert_oid_type(const struct object_id *oid, enum object_type expect);
 
 /*
diff --git a/t/t5329-pack-objects-cruft.sh b/t/t5329-pack-objects-cruft.sh
new file mode 100755
index 0000000000..003ca7344e
--- /dev/null
+++ b/t/t5329-pack-objects-cruft.sh
@@ -0,0 +1,218 @@
+#!/bin/sh
+
+test_description='cruft pack related pack-objects tests'
+. ./test-lib.sh
+
+objdir=.git/objects
+packdir=$objdir/pack
+
+basic_cruft_pack_tests () {
+	expire="$1"
+
+	test_expect_success "unreachable loose objects are packed (expire $expire)" '
+		git init repo &&
+		test_when_finished "rm -fr repo" &&
+		(
+			cd repo &&
+
+			test_commit base &&
+			git repack -Ad &&
+			test_commit loose &&
+
+			test-tool chmtime +2000 "$objdir/$(test_oid_to_path \
+				$(git rev-parse loose:loose.t))" &&
+			test-tool chmtime +1000 "$objdir/$(test_oid_to_path \
+				$(git rev-parse loose^{tree}))" &&
+
+			(
+				git rev-list --objects --no-object-names base..loose |
+				while read oid
+				do
+					path="$objdir/$(test_oid_to_path "$oid")" &&
+					printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")"
+				done |
+				sort -k1
+			) >expect &&
+
+			keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
+			cruft="$(echo $keep | git pack-objects --cruft \
+				--cruft-expiration="$expire" $packdir/pack)" &&
+			test-tool pack-mtimes "pack-$cruft.mtimes" >actual &&
+
+			test_cmp expect actual
+		)
+	'
+
+	test_expect_success "unreachable packed objects are packed (expire $expire)" '
+		git init repo &&
+		test_when_finished "rm -fr repo" &&
+		(
+			cd repo &&
+
+			test_commit packed &&
+			git repack -Ad &&
+			test_commit other &&
+
+			git rev-list --objects --no-object-names packed.. >objects &&
+			keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
+			other="$(git pack-objects --delta-base-offset \
+				$packdir/pack <objects)" &&
+			git prune-packed &&
+
+			test-tool chmtime --get -100 "$packdir/pack-$other.pack" >expect &&
+
+			cruft="$(git pack-objects --cruft --cruft-expiration="$expire" $packdir/pack <<-EOF
+			$keep
+			-pack-$other.pack
+			EOF
+			)" &&
+			test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw &&
+
+			cut -d" " -f2 <actual.raw | sort -u >actual &&
+
+			test_cmp expect actual
+		)
+	'
+
+	test_expect_success "unreachable cruft objects are repacked (expire $expire)" '
+		git init repo &&
+		test_when_finished "rm -fr repo" &&
+		(
+			cd repo &&
+
+			test_commit packed &&
+			git repack -Ad &&
+			test_commit other &&
+
+			git rev-list --objects --no-object-names packed.. >objects &&
+			keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
+
+			cruft_a="$(echo $keep | git pack-objects --cruft --cruft-expiration="$expire" $packdir/pack)" &&
+			git prune-packed &&
+			cruft_b="$(git pack-objects --cruft --cruft-expiration="$expire" $packdir/pack <<-EOF
+			$keep
+			-pack-$cruft_a.pack
+			EOF
+			)" &&
+
+			test-tool pack-mtimes "pack-$cruft_a.mtimes" >expect.raw &&
+			test-tool pack-mtimes "pack-$cruft_b.mtimes" >actual.raw &&
+
+			sort <expect.raw >expect &&
+			sort <actual.raw >actual &&
+
+			test_cmp expect actual
+		)
+	'
+
+	test_expect_success "multiple cruft packs (expire $expire)" '
+		git init repo &&
+		test_when_finished "rm -fr repo" &&
+		(
+			cd repo &&
+
+			test_commit reachable &&
+			git repack -Ad &&
+			keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
+
+			test_commit cruft &&
+			loose="$objdir/$(test_oid_to_path $(git rev-parse cruft))" &&
+
+			# generate three copies of the cruft object in different
+			# cruft packs, each with a unique mtime:
+			#   - one expired (1000 seconds ago)
+			#   - two non-expired (one 1000 seconds in the future,
+			#     one 1500 seconds in the future)
+			test-tool chmtime =-1000 "$loose" &&
+			git pack-objects --cruft $packdir/pack-A <<-EOF &&
+			$keep
+			EOF
+			test-tool chmtime =+1000 "$loose" &&
+			git pack-objects --cruft $packdir/pack-B <<-EOF &&
+			$keep
+			-$(basename $(ls $packdir/pack-A-*.pack))
+			EOF
+			test-tool chmtime =+1500 "$loose" &&
+			git pack-objects --cruft $packdir/pack-C <<-EOF &&
+			$keep
+			-$(basename $(ls $packdir/pack-A-*.pack))
+			-$(basename $(ls $packdir/pack-B-*.pack))
+			EOF
+
+			# ensure the resulting cruft pack takes the most recent
+			# mtime among all copies
+			cruft="$(git pack-objects --cruft \
+				--cruft-expiration="$expire" \
+				$packdir/pack <<-EOF
+			$keep
+			-$(basename $(ls $packdir/pack-A-*.pack))
+			-$(basename $(ls $packdir/pack-B-*.pack))
+			-$(basename $(ls $packdir/pack-C-*.pack))
+			EOF
+			)" &&
+
+			test-tool pack-mtimes "$(basename $(ls $packdir/pack-C-*.mtimes))" >expect.raw &&
+			test-tool pack-mtimes "pack-$cruft.mtimes" >actual.raw &&
+
+			sort expect.raw >expect &&
+			sort actual.raw >actual &&
+			test_cmp expect actual
+		)
+	'
+
+	test_expect_success "cruft packs tolerate missing trees (expire $expire)" '
+		git init repo &&
+		test_when_finished "rm -fr repo" &&
+		(
+			cd repo &&
+
+			test_commit reachable &&
+			test_commit cruft &&
+
+			tree="$(git rev-parse cruft^{tree})" &&
+
+			git reset --hard reachable &&
+			git tag -d cruft &&
+			git reflog expire --all --expire=all &&
+
+			# remove the unreachable tree, but leave the commit
+			# which has it as its root tree intact
+			rm -fr "$objdir/$(test_oid_to_path "$tree")" &&
+
+			git repack -Ad &&
+			basename $(ls $packdir/pack-*.pack) >in &&
+			git pack-objects --cruft --cruft-expiration="$expire" \
+				$packdir/pack <in
+		)
+	'
+
+	test_expect_success "cruft packs tolerate missing blobs (expire $expire)" '
+		git init repo &&
+		test_when_finished "rm -fr repo" &&
+		(
+			cd repo &&
+
+			test_commit reachable &&
+			test_commit cruft &&
+
+			blob="$(git rev-parse cruft:cruft.t)" &&
+
+			git reset --hard reachable &&
+			git tag -d cruft &&
+			git reflog expire --all --expire=all &&
+
+			# remove the unreachable blob, but leave the commit (and
+			# the root tree of that commit) intact
+			rm -fr "$objdir/$(test_oid_to_path "$blob")" &&
+
+			git repack -Ad &&
+			basename $(ls $packdir/pack-*.pack) >in &&
+			git pack-objects --cruft --cruft-expiration="$expire" \
+				$packdir/pack <in
+		)
+	'
+}
+
+basic_cruft_pack_tests never
+
+test_done
-- 
2.35.1.73.gccc5557600
Previous: Taylor BlauNext: Taylor Blau
Message 101 of 201 in “cruft packs”
  1. 00/17 cruft packsTaylor Blau, Nov 29, 2021
  2. 01/17 Documentation/technical: add cruft-packs.txtTaylor Blau, Nov 29, 2021
  3. Derrick StoleeDec 2, 2021
  4. Taylor BlauDec 3, 2021
  5. Elijah NewrenDec 4, 2021
  6. Taylor BlauDec 4, 2021
  7. 02/17 pack-mtimes: support reading .mtimes filesTaylor Blau, Nov 29, 2021
  8. Derrick StoleeDec 2, 2021
  9. brian m. carlsonDec 2, 2021
  10. Taylor BlauDec 3, 2021
  11. Taylor BlauJan 7, 2022
  12. 04/17 chunk-format.h: extract oid_version()Taylor Blau, Nov 29, 2021
  13. Derrick StoleeDec 2, 2021
  14. Taylor BlauDec 3, 2021
  15. Derrick StoleeDec 6, 2021
  16. 03/17 pack-write: pass 'struct packing_data' to 'stage_tmp_packfiles'Taylor Blau, Nov 29, 2021
  17. 05/17 pack-mtimes: support writing pack .mtimes filesTaylor Blau, Nov 29, 2021
  18. Derrick StoleeDec 2, 2021
  19. Taylor BlauDec 3, 2021
  20. 09/17 reachable: add options to add_unseen_recent_objects_to_traversalTaylor Blau, Nov 29, 2021
  21. 13/17 builtin/repack.c: allow configuring cruft pack generationTaylor Blau, Nov 29, 2021
  22. 06/17 t/helper: add 'pack-mtimes' test-toolTaylor Blau, Nov 29, 2021
  23. Derrick StoleeDec 6, 2021
  24. Taylor BlauFeb 23, 2022
  25. 11/17 builtin/pack-objects.c: --cruft with expirationTaylor Blau, Nov 29, 2021
  26. Derrick StoleeDec 7, 2021
  27. Taylor BlauFeb 23, 2022
  28. 10/17 reachable: report precise timestamps from objects in cruft packsTaylor Blau, Nov 29, 2021
  29. 07/17 builtin/pack-objects.c: return from create_object_entry()Taylor Blau, Nov 29, 2021
  30. 08/17 builtin/pack-objects.c: --cruft without expirationTaylor Blau, Nov 29, 2021
  31. Derrick StoleeDec 6, 2021
  32. Taylor BlauMar 1, 2022
  33. Derrick StoleeDec 7, 2021
  34. Taylor BlauFeb 23, 2022
  35. 12/17 builtin/repack.c: support generating a cruft packTaylor Blau, Nov 29, 2021
  36. Junio C HamanoDec 5, 2021
  37. Taylor BlauMar 1, 2022
  38. Derrick StoleeDec 7, 2021
  39. Taylor BlauFeb 23, 2022
  40. 15/17 builtin/repack.c: add cruft packs to MIDX during geometric repackTaylor Blau, Nov 29, 2021
  41. 16/17 builtin/gc.c: conditionally avoid pruning objects via looseTaylor Blau, Nov 29, 2021
  42. 17/17 sha1-file.c: don't freshen cruft packsTaylor Blau, Nov 29, 2021
  43. 14/17 builtin/repack.c: use named flags for existing_packsTaylor Blau, Nov 29, 2021
  44. Junio C HamanoDec 3, 2021
  45. Taylor BlauDec 3, 2021
  46. Taylor BlauDec 3, 2021
  47. 00/17 cruft packsTaylor Blau, Mar 2, 2022
  48. 01/17 Documentation/technical: add cruft-packs.txtTaylor Blau, Mar 2, 2022
  49. 03/17 pack-write: pass 'struct packing_data' to 'stage_tmp_packfiles'Taylor Blau, Mar 2, 2022
  50. 02/17 pack-mtimes: support reading .mtimes filesTaylor Blau, Mar 2, 2022
  51. Derrick StoleeMar 2, 2022
  52. Taylor BlauMar 2, 2022
  53. 04/17 chunk-format.h: extract oid_version()Taylor Blau, Mar 2, 2022
  54. 06/17 t/helper: add 'pack-mtimes' test-toolTaylor Blau, Mar 2, 2022
  55. 05/17 pack-mtimes: support writing pack .mtimes filesTaylor Blau, Mar 2, 2022
  56. 07/17 builtin/pack-objects.c: return from create_object_entry()Taylor Blau, Mar 2, 2022
  57. 08/17 builtin/pack-objects.c: --cruft without expirationTaylor Blau, Mar 2, 2022
  58. 09/17 reachable: add options to add_unseen_recent_objects_to_traversalTaylor Blau, Mar 2, 2022
  59. Derrick StoleeMar 2, 2022
  60. Taylor BlauMar 2, 2022
  61. 11/17 builtin/pack-objects.c: --cruft with expirationTaylor Blau, Mar 2, 2022
  62. Junio C HamanoMar 2, 2022
  63. Taylor BlauMar 2, 2022
  64. Derrick StoleeMar 2, 2022
  65. 10/17 reachable: report precise timestamps from objects in cruft packsTaylor Blau, Mar 2, 2022
  66. 13/17 builtin/repack.c: allow configuring cruft pack generationTaylor Blau, Mar 2, 2022
  67. 12/17 builtin/repack.c: support generating a cruft packTaylor Blau, Mar 2, 2022
  68. 14/17 builtin/repack.c: use named flags for existing_packsTaylor Blau, Mar 2, 2022
  69. 15/17 builtin/repack.c: add cruft packs to MIDX during geometric repackTaylor Blau, Mar 2, 2022
  70. 16/17 builtin/gc.c: conditionally avoid pruning objects via looseTaylor Blau, Mar 2, 2022
  71. 17/17 sha1-file.c: don't freshen cruft packsTaylor Blau, Mar 2, 2022
  72. Derrick StoleeMar 2, 2022
  73. Taylor BlauMar 2, 2022
  74. 00/17 cruft packsTaylor Blau, Mar 3, 2022
  75. 01/17 Documentation/technical: add cruft-packs.txtTaylor Blau, Mar 3, 2022
  76. Jonathan NiederMar 7, 2022
  77. Taylor BlauMar 22, 2022
  78. Jonathan NiederMar 22, 2022
  79. Taylor BlauMar 22, 2022
  80. Jonathan NiederMar 22, 2022
  81. Taylor BlauMar 23, 2022
  82. Taylor BlauMar 28, 2022
  83. Junio C HamanoMar 28, 2022
  84. Taylor BlauMar 28, 2022
  85. Junio C HamanoMar 29, 2022
  86. Taylor BlauMar 30, 2022
  87. Junio C HamanoMar 30, 2022
  88. Taylor BlauMar 30, 2022
  89. 03/17 pack-write: pass 'struct packing_data' to 'stage_tmp_packfiles'Taylor Blau, Mar 3, 2022
  90. 02/17 pack-mtimes: support reading .mtimes filesTaylor Blau, Mar 3, 2022
  91. 04/17 chunk-format.h: extract oid_version()Taylor Blau, Mar 3, 2022
  92. Ævar Arnfjörð BjarmasonMar 3, 2022
  93. Taylor BlauMar 3, 2022
  94. Junio C HamanoMar 4, 2022
  95. 05/17 pack-mtimes: support writing pack .mtimes filesTaylor Blau, Mar 3, 2022
  96. Ævar Arnfjörð BjarmasonMar 3, 2022
  97. Taylor BlauMar 3, 2022
  98. Ævar Arnfjörð BjarmasonMar 4, 2022
  99. 06/17 t/helper: add 'pack-mtimes' test-toolTaylor Blau, Mar 3, 2022
  100. 07/17 builtin/pack-objects.c: return from create_object_entry()Taylor Blau, Mar 3, 2022
  101. 08/17 builtin/pack-objects.c: --cruft without expirationTaylor Blau, Mar 3, 2022
  102. 09/17 reachable: add options to add_unseen_recent_objects_to_traversalTaylor Blau, Mar 3, 2022
  103. 10/17 reachable: report precise timestamps from objects in cruft packsTaylor Blau, Mar 3, 2022
  104. 11/17 builtin/pack-objects.c: --cruft with expirationTaylor Blau, Mar 3, 2022
  105. 12/17 builtin/repack.c: support generating a cruft packTaylor Blau, Mar 3, 2022
  106. 13/17 builtin/repack.c: allow configuring cruft pack generationTaylor Blau, Mar 3, 2022
  107. 14/17 builtin/repack.c: use named flags for existing_packsTaylor Blau, Mar 3, 2022
  108. 16/17 builtin/gc.c: conditionally avoid pruning objects via looseTaylor Blau, Mar 3, 2022
  109. 17/17 sha1-file.c: don't freshen cruft packsTaylor Blau, Mar 3, 2022
  110. 15/17 builtin/repack.c: add cruft packs to MIDX during geometric repackTaylor Blau, Mar 3, 2022
  111. Derrick StoleeMar 3, 2022
  112. 00/17 cruft packsTaylor Blau, May 18, 2022
  113. 01/17 Documentation/technical: add cruft-packs.txtTaylor Blau, May 18, 2022
  114. Junio C HamanoMay 19, 2022
  115. 02/17 pack-mtimes: support reading .mtimes filesTaylor Blau, May 18, 2022
  116. Ævar Arnfjörð BjarmasonMay 19, 2022
  117. Junio C HamanoMay 19, 2022
  118. Ævar Arnfjörð BjarmasonMay 20, 2022
  119. Taylor BlauMay 20, 2022
  120. 03/17 pack-write: pass 'struct packing_data' to 'stage_tmp_packfiles'Taylor Blau, May 18, 2022
  121. 06/17 t/helper: add 'pack-mtimes' test-toolTaylor Blau, May 18, 2022
  122. 07/17 builtin/pack-objects.c: return from create_object_entry()Taylor Blau, May 18, 2022
  123. 10/17 reachable: report precise timestamps from objects in cruft packsTaylor Blau, May 18, 2022
  124. 09/17 reachable: add options to add_unseen_recent_objects_to_traversalTaylor Blau, May 18, 2022
  125. 08/17 builtin/pack-objects.c: --cruft without expirationTaylor Blau, May 18, 2022
  126. Junio C HamanoMay 19, 2022
  127. Junio C HamanoMay 19, 2022
  128. Taylor BlauMay 20, 2022
  129. 11/17 builtin/pack-objects.c: --cruft with expirationTaylor Blau, May 18, 2022
  130. 12/17 builtin/repack.c: support generating a cruft packTaylor Blau, May 18, 2022
  131. Ævar Arnfjörð BjarmasonMay 19, 2022
  132. Taylor BlauMay 20, 2022
  133. 04/17 chunk-format.h: extract oid_version()Taylor Blau, May 18, 2022
  134. Ævar Arnfjörð BjarmasonMay 19, 2022
  135. 05/17 pack-mtimes: support writing pack .mtimes filesTaylor Blau, May 18, 2022
  136. 13/17 builtin/repack.c: allow configuring cruft pack generationTaylor Blau, May 18, 2022
  137. 14/17 builtin/repack.c: use named flags for existing_packsTaylor Blau, May 18, 2022
  138. 15/17 builtin/repack.c: add cruft packs to MIDX during geometric repackTaylor Blau, May 18, 2022
  139. Ævar Arnfjörð BjarmasonMay 19, 2022
  140. Taylor BlauMay 20, 2022
  141. 16/17 builtin/gc.c: conditionally avoid pruning objects via looseTaylor Blau, May 18, 2022
  142. 17/17 sha1-file.c: don't freshen cruft packsTaylor Blau, May 18, 2022
  143. Derrick StoleeMay 18, 2022
  144. Junio C HamanoMay 20, 2022
  145. Taylor BlauMay 20, 2022
  146. 0/2 Utility functions for duplicated pack(write) codeÆvar Arnfjörð Bjarmason, May 19, 2022
  147. 1/2 packfile API: add and use a pack_name_to_ext() utility functionÆvar Arnfjörð Bjarmason, May 19, 2022
  148. Junio C HamanoMay 19, 2022
  149. 2/2 hash API: add and use a hash_short_id_by_algo() functionÆvar Arnfjörð Bjarmason, May 19, 2022
  150. Junio C HamanoMay 19, 2022
  151. Ævar Arnfjörð BjarmasonMay 19, 2022
  152. Junio C HamanoMay 19, 2022
  153. Ævar Arnfjörð BjarmasonMay 19, 2022
  154. 00/17 cruft packsTaylor Blau, May 20, 2022
  155. 01/17 Documentation/technical: add cruft-packs.txtTaylor Blau, May 20, 2022
  156. 05/17 pack-mtimes: support writing pack .mtimes filesTaylor Blau, May 20, 2022
  157. 04/17 chunk-format.h: extract oid_version()Taylor Blau, May 20, 2022
  158. 03/17 pack-write: pass 'struct packing_data' to 'stage_tmp_packfiles'Taylor Blau, May 20, 2022
  159. 06/17 t/helper: add 'pack-mtimes' test-toolTaylor Blau, May 20, 2022
  160. 07/17 builtin/pack-objects.c: return from create_object_entry()Taylor Blau, May 20, 2022
  161. 02/17 pack-mtimes: support reading .mtimes filesTaylor Blau, May 20, 2022
  162. Jonathan NiederMay 24, 2022
  163. rsbecker@nexbridge.comMay 24, 2022
  164. Taylor BlauMay 24, 2022
  165. rsbecker@nexbridge.comMay 24, 2022
  166. Taylor BlauMay 25, 2022
  167. rsbecker@nexbridge.comMay 25, 2022
  168. adding new 32-bit on-disk (unsigned) timestamp formats (was: [PATCH v5 02/17] pack-mtimes: support reading .mtimes files)Ævar Arnfjörð Bjarmason, May 25, 2022
  169. Derrick StoleeMay 25, 2022
  170. Taylor BlauMay 25, 2022
  171. Ævar Arnfjörð BjarmasonMay 26, 2022
  172. Taylor BlauMay 26, 2022
  173. Taylor BlauMay 24, 2022
  174. Jonathan NiederMay 25, 2022
  175. Taylor BlauMay 25, 2022
  176. rsbecker@nexbridge.comMay 25, 2022
  177. Taylor BlauMay 25, 2022
  178. Taylor BlauMay 25, 2022
  179. Junio C HamanoMay 26, 2022
  180. Andreas SchwabJun 1, 2023
  181. 08/17 builtin/pack-objects.c: --cruft without expirationTaylor Blau, May 20, 2022
  182. 10/17 reachable: report precise timestamps from objects in cruft packsTaylor Blau, May 20, 2022
  183. 09/17 reachable: add options to add_unseen_recent_objects_to_traversalTaylor Blau, May 20, 2022
  184. 11/17 builtin/pack-objects.c: --cruft with expirationTaylor Blau, May 20, 2022
  185. 12/17 builtin/repack.c: support generating a cruft packTaylor Blau, May 20, 2022
  186. 13/17 builtin/repack.c: allow configuring cruft pack generationTaylor Blau, May 20, 2022
  187. 15/17 builtin/repack.c: add cruft packs to MIDX during geometric repackTaylor Blau, May 20, 2022
  188. 14/17 builtin/repack.c: use named flags for existing_packsTaylor Blau, May 20, 2022
  189. 17/17 sha1-file.c: don't freshen cruft packsTaylor Blau, May 20, 2022
  190. 16/17 builtin/gc.c: conditionally avoid pruning objects via looseTaylor Blau, May 20, 2022
  191. René ScharfeJun 19, 2022
  192. Junio C HamanoJun 21, 2022
  193. Ævar Arnfjörð BjarmasonMay 21, 2022
  194. Jonathan NiederMay 24, 2022
  195. Taylor BlauMay 24, 2022
  196. Ævar Arnfjörð BjarmasonMay 24, 2022
  197. Taylor BlauMay 24, 2022
  198. Jonathan NiederMay 25, 2022
  199. Derrick StoleeMay 25, 2022
  200. Taylor BlauMay 25, 2022
  201. Ævar Arnfjörð BjarmasonMay 26, 2022

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.