diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | builtin-clone.c | 8 | ||||
| -rw-r--r-- | builtin-fetch-pack.c | 1 | ||||
| -rw-r--r-- | builtin-pack-refs.c | 121 | ||||
| -rw-r--r-- | pack-refs.c | 117 | ||||
| -rw-r--r-- | pack-refs.h | 18 | ||||
| -rwxr-xr-x | t/t5515-fetch-merge-logic.sh | 9 | 
7 files changed, 151 insertions, 125 deletions
| @@ -354,6 +354,7 @@ LIB_H += log-tree.h  LIB_H += mailmap.h  LIB_H += object.h  LIB_H += pack.h +LIB_H += pack-refs.h  LIB_H += pack-revindex.h  LIB_H += parse-options.h  LIB_H += patch-ids.h @@ -429,6 +430,7 @@ LIB_OBJS += merge-file.o  LIB_OBJS += name-hash.o  LIB_OBJS += object.o  LIB_OBJS += pack-check.o +LIB_OBJS += pack-refs.o  LIB_OBJS += pack-revindex.o  LIB_OBJS += pack-write.o  LIB_OBJS += pager.o diff --git a/builtin-clone.c b/builtin-clone.c index b2dfe1ab5c..f13845fb7f 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -18,6 +18,7 @@  #include "transport.h"  #include "strbuf.h"  #include "dir.h" +#include "pack-refs.h"  /*   * Overall FIXMEs: @@ -321,8 +322,11 @@ static struct ref *write_remote_refs(const struct ref *refs,  	get_fetch_map(refs, tag_refspec, &tail, 0);  	for (r = local_refs; r; r = r->next) -		update_ref(reflog, -			   r->peer_ref->name, r->old_sha1, NULL, 0, DIE_ON_ERR); +		add_extra_ref(r->peer_ref->name, r->old_sha1, 0); + +	pack_refs(PACK_REFS_ALL); +	clear_extra_refs(); +  	return local_refs;  } diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index de1e8d1365..f4dbcf069e 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -820,5 +820,6 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,  		}  	} +	reprepare_packed_git();  	return ref_cpy;  } diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c index 1aaa76dd1f..ff90aefa1c 100644 --- a/builtin-pack-refs.c +++ b/builtin-pack-refs.c @@ -1,125 +1,6 @@ -#include "builtin.h"  #include "cache.h" -#include "refs.h" -#include "object.h" -#include "tag.h"  #include "parse-options.h" - -struct ref_to_prune { -	struct ref_to_prune *next; -	unsigned char sha1[20]; -	char name[FLEX_ARRAY]; -}; - -#define PACK_REFS_PRUNE	0x0001 -#define PACK_REFS_ALL	0x0002 - -struct pack_refs_cb_data { -	unsigned int flags; -	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->flags & PACK_REFS_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->flags & PACK_REFS_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; - -static int pack_refs(unsigned int flags) -{ -	int fd; -	struct pack_refs_cb_data cbdata; - -	memset(&cbdata, 0, sizeof(cbdata)); -	cbdata.flags = flags; - -	fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 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); -	if (ferror(cbdata.refs_file)) -		die("failed to write ref-pack file"); -	if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file)) -		die("failed to write ref-pack file (%s)", strerror(errno)); -	/* -	 * Since the lock file was fdopen()'ed and then fclose()'ed above, -	 * assign -1 to the lock file descriptor so that commit_lock_file() -	 * won't try to close() it. -	 */ -	packed.fd = -1; -	if (commit_lock_file(&packed) < 0) -		die("unable to overwrite old ref-pack file (%s)", strerror(errno)); -	if (cbdata.flags & PACK_REFS_PRUNE) -		prune_refs(cbdata.ref_to_prune); -	return 0; -} +#include "pack-refs.h"  static char const * const pack_refs_usage[] = {  	"git-pack-refs [options]", diff --git a/pack-refs.c b/pack-refs.c new file mode 100644 index 0000000000..848d311c2b --- /dev/null +++ b/pack-refs.c @@ -0,0 +1,117 @@ +#include "cache.h" +#include "refs.h" +#include "tag.h" +#include "pack-refs.h" + +struct ref_to_prune { +	struct ref_to_prune *next; +	unsigned char sha1[20]; +	char name[FLEX_ARRAY]; +}; + +struct pack_refs_cb_data { +	unsigned int flags; +	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->flags & PACK_REFS_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->flags & PACK_REFS_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 pack_refs(unsigned int flags) +{ +	int fd; +	struct pack_refs_cb_data cbdata; + +	memset(&cbdata, 0, sizeof(cbdata)); +	cbdata.flags = flags; + +	fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 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); +	if (ferror(cbdata.refs_file)) +		die("failed to write ref-pack file"); +	if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file)) +		die("failed to write ref-pack file (%s)", strerror(errno)); +	/* +	 * Since the lock file was fdopen()'ed and then fclose()'ed above, +	 * assign -1 to the lock file descriptor so that commit_lock_file() +	 * won't try to close() it. +	 */ +	packed.fd = -1; +	if (commit_lock_file(&packed) < 0) +		die("unable to overwrite old ref-pack file (%s)", strerror(errno)); +	if (cbdata.flags & PACK_REFS_PRUNE) +		prune_refs(cbdata.ref_to_prune); +	return 0; +} diff --git a/pack-refs.h b/pack-refs.h new file mode 100644 index 0000000000..518acfb370 --- /dev/null +++ b/pack-refs.h @@ -0,0 +1,18 @@ +#ifndef PACK_REFS_H +#define PACK_REFS_H + +/* + * Flags for controlling behaviour of pack_refs() + * PACK_REFS_PRUNE: Prune loose refs after packing + * PACK_REFS_ALL:   Pack _all_ refs, not just tags and already packed refs + */ +#define PACK_REFS_PRUNE 0x0001 +#define PACK_REFS_ALL   0x0002 + +/* + * Write a packed-refs file for the current repository. + * flags: Combination of the above PACK_REFS_* flags. + */ +int pack_refs(unsigned int flags); + +#endif /* PACK_REFS_H */ diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index 3def75eeb2..8becbc3f38 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -142,9 +142,12 @@ do  			set x $cmd; shift  			git symbolic-ref HEAD refs/heads/$1 ; shift  			rm -f .git/FETCH_HEAD -			rm -f .git/refs/heads/* -			rm -f .git/refs/remotes/rem/* -			rm -f .git/refs/tags/* +			git for-each-ref \ +				refs/heads refs/remotes/rem refs/tags | +			while read val type refname +			do +				git update-ref -d "$refname" "$val" +			done  			git fetch "$@" >/dev/null  			cat .git/FETCH_HEAD  		} >"$actual_f" && | 
