Remove pack.keep after ref updates in git-fetch
If we are using a native packfile to perform a git-fetch invocation
and the received packfile contained more than the configured limits
of fetch.unpackLimit/transfer.unpackLimit then index-pack will output
a single line saying "keep\t$sha1\n" to stdout.  This line needs to
be captured and retained so we can delete the corresponding .keep
file ("$GIT_DIR/objects/pack/pack-$sha1.keep") once all refs have
been safely updated.
This trick has long been in use with git-fetch.sh and its lower level
helper git-fetch--tool as a way to allow index-pack to save the new
packfile before the refs have been updated and yet avoid a race with
any concurrently running git-repack process.  It was unfortunately
lost when git-fetch.sh was converted to pure C and fetch--tool was
no longer being invoked.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
			
			
This commit is contained in:
		
				
					committed by
					
						
						Junio C Hamano
					
				
			
			
				
	
			
			
			
						parent
						
							106764e651
						
					
				
				
					commit
					1788c39cd0
				
			@ -493,7 +493,7 @@ static pid_t setup_sideband(int fd[2], int xd[2])
 | 
			
		||||
	return side_pid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_pack(int xd[2])
 | 
			
		||||
static int get_pack(int xd[2], char **pack_lockfile)
 | 
			
		||||
{
 | 
			
		||||
	int status;
 | 
			
		||||
	pid_t pid, side_pid;
 | 
			
		||||
@ -503,6 +503,7 @@ static int get_pack(int xd[2])
 | 
			
		||||
	char hdr_arg[256];
 | 
			
		||||
	const char **av;
 | 
			
		||||
	int do_keep = keep_pack;
 | 
			
		||||
	int keep_pipe[2];
 | 
			
		||||
 | 
			
		||||
	side_pid = setup_sideband(fd, xd);
 | 
			
		||||
 | 
			
		||||
@ -522,6 +523,8 @@ static int get_pack(int xd[2])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (do_keep) {
 | 
			
		||||
		if (pack_lockfile && pipe(keep_pipe))
 | 
			
		||||
			die("fetch-pack: pipe setup failure: %s", strerror(errno));
 | 
			
		||||
		*av++ = "index-pack";
 | 
			
		||||
		*av++ = "--stdin";
 | 
			
		||||
		if (!quiet && !no_progress)
 | 
			
		||||
@ -550,6 +553,11 @@ static int get_pack(int xd[2])
 | 
			
		||||
		die("fetch-pack: unable to fork off %s", argv[0]);
 | 
			
		||||
	if (!pid) {
 | 
			
		||||
		dup2(fd[0], 0);
 | 
			
		||||
		if (do_keep && pack_lockfile) {
 | 
			
		||||
			dup2(keep_pipe[1], 1);
 | 
			
		||||
			close(keep_pipe[0]);
 | 
			
		||||
			close(keep_pipe[1]);
 | 
			
		||||
		}
 | 
			
		||||
		close(fd[0]);
 | 
			
		||||
		close(fd[1]);
 | 
			
		||||
		execv_git_cmd(argv);
 | 
			
		||||
@ -557,6 +565,11 @@ static int get_pack(int xd[2])
 | 
			
		||||
	}
 | 
			
		||||
	close(fd[0]);
 | 
			
		||||
	close(fd[1]);
 | 
			
		||||
	if (do_keep && pack_lockfile) {
 | 
			
		||||
		close(keep_pipe[1]);
 | 
			
		||||
		*pack_lockfile = index_pack_lockfile(keep_pipe[0]);
 | 
			
		||||
		close(keep_pipe[0]);
 | 
			
		||||
	}
 | 
			
		||||
	while (waitpid(pid, &status, 0) < 0) {
 | 
			
		||||
		if (errno != EINTR)
 | 
			
		||||
			die("waiting for %s: %s", argv[0], strerror(errno));
 | 
			
		||||
@ -574,7 +587,10 @@ static int get_pack(int xd[2])
 | 
			
		||||
	die("%s died of unnatural causes %d", argv[0], status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct ref *do_fetch_pack(int fd[2], int nr_match, char **match)
 | 
			
		||||
static struct ref *do_fetch_pack(int fd[2],
 | 
			
		||||
		int nr_match,
 | 
			
		||||
		char **match,
 | 
			
		||||
		char **pack_lockfile)
 | 
			
		||||
{
 | 
			
		||||
	struct ref *ref;
 | 
			
		||||
	unsigned char sha1[20];
 | 
			
		||||
@ -612,7 +628,7 @@ static struct ref *do_fetch_pack(int fd[2], int nr_match, char **match)
 | 
			
		||||
			 */
 | 
			
		||||
			fprintf(stderr, "warning: no common commits\n");
 | 
			
		||||
 | 
			
		||||
	if (get_pack(fd))
 | 
			
		||||
	if (get_pack(fd, pack_lockfile))
 | 
			
		||||
		die("git-fetch-pack: fetch failed.");
 | 
			
		||||
 | 
			
		||||
 all_done:
 | 
			
		||||
@ -741,7 +757,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 | 
			
		||||
	if (!dest)
 | 
			
		||||
		usage(fetch_pack_usage);
 | 
			
		||||
 | 
			
		||||
	ref = fetch_pack(dest, nr_heads, heads);
 | 
			
		||||
	ref = fetch_pack(dest, nr_heads, heads, NULL);
 | 
			
		||||
 | 
			
		||||
	ret = !ref;
 | 
			
		||||
 | 
			
		||||
@ -754,7 +770,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ref *fetch_pack(const char *dest, int nr_heads, char **heads)
 | 
			
		||||
struct ref *fetch_pack(const char *dest,
 | 
			
		||||
		int nr_heads,
 | 
			
		||||
		char **heads,
 | 
			
		||||
		char **pack_lockfile)
 | 
			
		||||
{
 | 
			
		||||
	int i, ret;
 | 
			
		||||
	int fd[2];
 | 
			
		||||
@ -773,7 +792,7 @@ struct ref *fetch_pack(const char *dest, int nr_heads, char **heads)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	if (heads && nr_heads)
 | 
			
		||||
		nr_heads = remove_duplicates(nr_heads, heads);
 | 
			
		||||
	ref = do_fetch_pack(fd, nr_heads, heads);
 | 
			
		||||
	ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile);
 | 
			
		||||
	close(fd[0]);
 | 
			
		||||
	close(fd[1]);
 | 
			
		||||
	ret = finish_connect(pid);
 | 
			
		||||
 | 
			
		||||
@ -274,6 +274,7 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
 | 
			
		||||
	int ret = transport_fetch_refs(transport, ref_map);
 | 
			
		||||
	if (!ret)
 | 
			
		||||
		store_updated_refs(transport->url, ref_map);
 | 
			
		||||
	transport_unlock_pack(transport);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,6 @@ struct fetch_pack_args
 | 
			
		||||
 | 
			
		||||
void setup_fetch_pack(struct fetch_pack_args *args);
 | 
			
		||||
 | 
			
		||||
struct ref *fetch_pack(const char *dest, int nr_heads, char **heads);
 | 
			
		||||
struct ref *fetch_pack(const char *dest, int nr_heads, char **heads, char **pack_lockfile);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								transport.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								transport.c
									
									
									
									
									
								
							@ -9,7 +9,7 @@
 | 
			
		||||
 | 
			
		||||
/* Generic functions for using commit walkers */
 | 
			
		||||
 | 
			
		||||
static int fetch_objs_via_walker(const struct transport *transport,
 | 
			
		||||
static int fetch_objs_via_walker(struct transport *transport,
 | 
			
		||||
				 int nr_objs, struct ref **to_fetch)
 | 
			
		||||
{
 | 
			
		||||
	char *dest = xstrdup(transport->url);
 | 
			
		||||
@ -219,7 +219,7 @@ static struct ref *get_refs_from_bundle(const struct transport *transport)
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fetch_refs_from_bundle(const struct transport *transport,
 | 
			
		||||
static int fetch_refs_from_bundle(struct transport *transport,
 | 
			
		||||
			       int nr_heads, struct ref **to_fetch)
 | 
			
		||||
{
 | 
			
		||||
	struct bundle_transport_data *data = transport->data;
 | 
			
		||||
@ -306,7 +306,7 @@ static struct ref *get_refs_via_connect(const struct transport *transport)
 | 
			
		||||
	return refs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fetch_refs_via_pack(const struct transport *transport,
 | 
			
		||||
static int fetch_refs_via_pack(struct transport *transport,
 | 
			
		||||
			       int nr_heads, struct ref **to_fetch)
 | 
			
		||||
{
 | 
			
		||||
	struct git_transport_data *data = transport->data;
 | 
			
		||||
@ -330,7 +330,7 @@ static int fetch_refs_via_pack(const struct transport *transport,
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < nr_heads; i++)
 | 
			
		||||
		heads[i] = xstrdup(to_fetch[i]->name);
 | 
			
		||||
	refs = fetch_pack(dest, nr_heads, heads);
 | 
			
		||||
	refs = fetch_pack(dest, nr_heads, heads, &transport->pack_lockfile);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < nr_heads; i++)
 | 
			
		||||
		free(heads[i]);
 | 
			
		||||
@ -445,6 +445,7 @@ struct transport *transport_get(struct remote *remote, const char *url,
 | 
			
		||||
		ret->url = url;
 | 
			
		||||
		ret->remote_refs = NULL;
 | 
			
		||||
		ret->fetch = !!fetch;
 | 
			
		||||
		ret->pack_lockfile = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
@ -500,6 +501,15 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void transport_unlock_pack(struct transport *transport)
 | 
			
		||||
{
 | 
			
		||||
	if (transport->pack_lockfile) {
 | 
			
		||||
		unlink(transport->pack_lockfile);
 | 
			
		||||
		free(transport->pack_lockfile);
 | 
			
		||||
		transport->pack_lockfile = NULL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int transport_disconnect(struct transport *transport)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@ struct transport {
 | 
			
		||||
	struct ref *remote_refs;
 | 
			
		||||
 | 
			
		||||
	const struct transport_ops *ops;
 | 
			
		||||
	char *pack_lockfile;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define TRANSPORT_PUSH_ALL 1
 | 
			
		||||
@ -30,7 +31,7 @@ struct transport_ops {
 | 
			
		||||
			  const char *value);
 | 
			
		||||
 | 
			
		||||
	struct ref *(*get_refs_list)(const struct transport *transport);
 | 
			
		||||
	int (*fetch)(const struct transport *transport, int refs_nr, struct ref **refs);
 | 
			
		||||
	int (*fetch)(struct transport *transport, int refs_nr, struct ref **refs);
 | 
			
		||||
	int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
 | 
			
		||||
 | 
			
		||||
	int (*disconnect)(struct transport *connection);
 | 
			
		||||
@ -73,7 +74,7 @@ int transport_push(struct transport *connection,
 | 
			
		||||
struct ref *transport_get_remote_refs(struct transport *transport);
 | 
			
		||||
 | 
			
		||||
int transport_fetch_refs(struct transport *transport, struct ref *refs);
 | 
			
		||||
 | 
			
		||||
void transport_unlock_pack(struct transport *transport);
 | 
			
		||||
int transport_disconnect(struct transport *transport);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user