Merge branch 'jk/close-duped-fd-before-unlock-for-bundle'
When "git bundle" aborts due to an empty commit ranges (i.e. resulting in an empty pack), it left a file descriptor to an lockfile open, which resulted in leftover lockfile on Windows where you cannot remove a file with an open file descriptor. This has been corrected. * jk/close-duped-fd-before-unlock-for-bundle: bundle: dup() output descriptor closer to point-of-use
This commit is contained in:
commit
9e3dc6bfb2
39
bundle.c
39
bundle.c
@ -243,7 +243,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Write the pack data to bundle_fd, then close it if it is > 1. */
|
/* Write the pack data to bundle_fd */
|
||||||
static int write_pack_data(int bundle_fd, struct rev_info *revs)
|
static int write_pack_data(int bundle_fd, struct rev_info *revs)
|
||||||
{
|
{
|
||||||
struct child_process pack_objects = CHILD_PROCESS_INIT;
|
struct child_process pack_objects = CHILD_PROCESS_INIT;
|
||||||
@ -256,6 +256,20 @@ static int write_pack_data(int bundle_fd, struct rev_info *revs)
|
|||||||
pack_objects.in = -1;
|
pack_objects.in = -1;
|
||||||
pack_objects.out = bundle_fd;
|
pack_objects.out = bundle_fd;
|
||||||
pack_objects.git_cmd = 1;
|
pack_objects.git_cmd = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start_command() will close our descriptor if it's >1. Duplicate it
|
||||||
|
* to avoid surprising the caller.
|
||||||
|
*/
|
||||||
|
if (pack_objects.out > 1) {
|
||||||
|
pack_objects.out = dup(pack_objects.out);
|
||||||
|
if (pack_objects.out < 0) {
|
||||||
|
error_errno(_("unable to dup bundle descriptor"));
|
||||||
|
child_process_clear(&pack_objects);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (start_command(&pack_objects))
|
if (start_command(&pack_objects))
|
||||||
return error(_("Could not spawn pack-objects"));
|
return error(_("Could not spawn pack-objects"));
|
||||||
|
|
||||||
@ -421,21 +435,10 @@ int create_bundle(struct bundle_header *header, const char *path,
|
|||||||
bundle_to_stdout = !strcmp(path, "-");
|
bundle_to_stdout = !strcmp(path, "-");
|
||||||
if (bundle_to_stdout)
|
if (bundle_to_stdout)
|
||||||
bundle_fd = 1;
|
bundle_fd = 1;
|
||||||
else {
|
else
|
||||||
bundle_fd = hold_lock_file_for_update(&lock, path,
|
bundle_fd = hold_lock_file_for_update(&lock, path,
|
||||||
LOCK_DIE_ON_ERROR);
|
LOCK_DIE_ON_ERROR);
|
||||||
|
|
||||||
/*
|
|
||||||
* write_pack_data() will close the fd passed to it,
|
|
||||||
* but commit_lock_file() will also try to close the
|
|
||||||
* lockfile's fd. So make a copy of the file
|
|
||||||
* descriptor to avoid trying to close it twice.
|
|
||||||
*/
|
|
||||||
bundle_fd = dup(bundle_fd);
|
|
||||||
if (bundle_fd < 0)
|
|
||||||
die_errno("unable to dup file descriptor");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write signature */
|
/* write signature */
|
||||||
write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
|
write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
|
||||||
|
|
||||||
@ -463,10 +466,8 @@ int create_bundle(struct bundle_header *header, const char *path,
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* write pack */
|
/* write pack */
|
||||||
if (write_pack_data(bundle_fd, &revs)) {
|
if (write_pack_data(bundle_fd, &revs))
|
||||||
bundle_fd = -1; /* already closed by the above call */
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
|
|
||||||
if (!bundle_to_stdout) {
|
if (!bundle_to_stdout) {
|
||||||
if (commit_lock_file(&lock))
|
if (commit_lock_file(&lock))
|
||||||
@ -474,11 +475,7 @@ int create_bundle(struct bundle_header *header, const char *path,
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
if (!bundle_to_stdout) {
|
rollback_lock_file(&lock);
|
||||||
if (0 <= bundle_fd)
|
|
||||||
close(bundle_fd);
|
|
||||||
rollback_lock_file(&lock);
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,4 +71,10 @@ test_expect_success 'prerequisites with an empty commit message' '
|
|||||||
git bundle verify bundle
|
git bundle verify bundle
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'failed bundle creation does not leave cruft' '
|
||||||
|
# This fails because the bundle would be empty.
|
||||||
|
test_must_fail git bundle create fail.bundle master..master &&
|
||||||
|
test_path_is_missing fail.bundle.lock
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user