git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
blob afa9b5a00be7d01e4d7fc7595cc7ea283aa481ae 3349 bytes (raw)
name: builtin-pack-refs.c 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
 
#include "cache.h"
#include "refs.h"
#include "object.h"
#include "tag.h"

static const char builtin_pack_refs_usage[] =
"git-pack-refs [--all] [--prune | --no-prune]";

struct ref_to_prune {
	struct ref_to_prune *next;
	unsigned char sha1[20];
	char name[FLEX_ARRAY];
};

struct pack_refs_cb_data {
	int prune;
	int all;
	struct ref_to_prune *ref_to_prune;
	FILE *refs_file;
};

static int do_not_prune(int flags)
{
	/* If it is already packed or if it is a symref,
	 * do not prune it.
	 */
	return (flags & (REF_ISSYMREF|REF_ISPACKED));
}

static int handle_one_ref(const char *path, const unsigned char *sha1,
			  int flags, void *cb_data)
{
	struct pack_refs_cb_data *cb = cb_data;
	int is_tag_ref;

	/* Do not pack the symbolic refs */
	if ((flags & REF_ISSYMREF))
		return 0;
	is_tag_ref = !prefixcmp(path, "refs/tags/");

	/* ALWAYS pack refs that were already packed or are tags */
	if (!cb->all && !is_tag_ref && !(flags & REF_ISPACKED))
		return 0;

	fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
	if (is_tag_ref) {
		struct object *o = parse_object(sha1);
		if (o->type == OBJ_TAG) {
			o = deref_tag(o, path, 0);
			if (o)
				fprintf(cb->refs_file, "^%s\n",
					sha1_to_hex(o->sha1));
		}
	}

	if (cb->prune && !do_not_prune(flags)) {
		int namelen = strlen(path) + 1;
		struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
		hashcpy(n->sha1, sha1);
		strcpy(n->name, path);
		n->next = cb->ref_to_prune;
		cb->ref_to_prune = n;
	}
	return 0;
}

/* make sure nobody touched the ref, and unlink */
static void prune_ref(struct ref_to_prune *r)
{
	struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);

	if (lock) {
		unlink(git_path("%s", r->name));
		unlock_ref(lock);
	}
}

static void prune_refs(struct ref_to_prune *r)
{
	while (r) {
		prune_ref(r);
		r = r->next;
	}
}

static struct lock_file packed;

int cmd_pack_refs(int argc, const char **argv, const char *prefix)
{
	int fd, i;
	struct pack_refs_cb_data cbdata;
	struct stat st;
	char *ref_file_name;

	memset(&cbdata, 0, sizeof(cbdata));

	cbdata.prune = 1;
	for (i = 1; i < argc; i++) {
		const char *arg = argv[i];
		if (!strcmp(arg, "--prune")) {
			cbdata.prune = 1; /* now the default */
			continue;
		}
		if (!strcmp(arg, "--no-prune")) {
			cbdata.prune = 0;
			continue;
		}
		if (!strcmp(arg, "--all")) {
			cbdata.all = 1;
			continue;
		}
		/* perhaps other parameters later... */
		break;
	}
	if (i != argc)
		usage(builtin_pack_refs_usage);

	ref_file_name = git_path("packed-refs");
	if (!lstat(ref_file_name, &st) && S_ISLNK(st.st_mode)) {
		char *buf = xmalloc(st.st_size + 1);
		if (readlink(ref_file_name, buf, st.st_size + 1) != st.st_size) {
			free(buf);
			die("readlink failed\n");
		}
		buf[st.st_size] = '\0';
		ref_file_name = buf;
	}

	fd = hold_lock_file_for_update(&packed, ref_file_name, 1);
	cbdata.refs_file = fdopen(fd, "w");
	if (!cbdata.refs_file)
		die("unable to create ref-pack file structure (%s)",
		    strerror(errno));

	/* perhaps other traits later as well */
	fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");

	for_each_ref(handle_one_ref, &cbdata);
	fflush(cbdata.refs_file);
	fsync(fd);
	fclose(cbdata.refs_file);
	if (commit_lock_file(&packed) < 0)
		die("unable to overwrite old ref-pack file (%s)", strerror(errno));
	if (cbdata.prune)
		prune_refs(cbdata.ref_to_prune);
	return 0;
}

debug log:

solving afa9b5a ...
found afa9b5a in https://public-inbox.org/git/20070418102823.GA5586@xp.machine.xx/
found d080e30 in https://80x24.org/mirrors/git.git
preparing index
index prepared:
100644 d080e30d67a913529d46e0da169faa4b0be75580	builtin-pack-refs.c

applying [1/1] https://public-inbox.org/git/20070418102823.GA5586@xp.machine.xx/
diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c
index d080e30..afa9b5a 100644

Checking patch builtin-pack-refs.c...
Applied patch builtin-pack-refs.c cleanly.

index at:
100644 afa9b5a00be7d01e4d7fc7595cc7ea283aa481ae	builtin-pack-refs.c

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).