Skip to content

Commit f836a32

Browse files
committed
Merge branch 'js/clone-dissociate' into maint
"git clone --dissociate" runs a big "git repack" process at the end, and it helps to close file descriptors that are open on the packs and their idx files before doing so on filesystems that cannot remove a file that is still open. * js/clone-dissociate: clone --dissociate: avoid locking pack files sha1_file.c: add a function to release all packs sha1_file: consolidate code to close a pack's file descriptor t5700: demonstrate a Windows file locking issue with `git clone --dissociate`
2 parents 04bba3a + 786b150 commit f836a32

File tree

4 files changed

+62
-23
lines changed

4 files changed

+62
-23
lines changed

builtin/clone.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1064,8 +1064,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
10641064
transport_unlock_pack(transport);
10651065
transport_disconnect(transport);
10661066

1067-
if (option_dissociate)
1067+
if (option_dissociate) {
1068+
close_all_packs();
10681069
dissociate_from_references();
1070+
}
10691071

10701072
junk_mode = JUNK_LEAVE_REPO;
10711073
err = checkout();

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,7 @@ extern void close_pack_index(struct packed_git *);
12821282

12831283
extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *);
12841284
extern void close_pack_windows(struct packed_git *);
1285+
extern void close_all_packs(void);
12851286
extern void unuse_pack(struct pack_window **);
12861287
extern void free_pack_by_name(const char *);
12871288
extern void clear_delta_base_cache(void);

sha1_file.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,37 @@ void close_pack_windows(struct packed_git *p)
786786
}
787787
}
788788

789+
static int close_pack_fd(struct packed_git *p)
790+
{
791+
if (p->pack_fd < 0)
792+
return 0;
793+
794+
close(p->pack_fd);
795+
pack_open_fds--;
796+
p->pack_fd = -1;
797+
798+
return 1;
799+
}
800+
801+
static void close_pack(struct packed_git *p)
802+
{
803+
close_pack_windows(p);
804+
close_pack_fd(p);
805+
close_pack_index(p);
806+
}
807+
808+
void close_all_packs(void)
809+
{
810+
struct packed_git *p;
811+
812+
for (p = packed_git; p; p = p->next)
813+
if (p->do_not_close)
814+
die("BUG! Want to close pack marked 'do-not-close'");
815+
else
816+
close_pack(p);
817+
}
818+
819+
789820
/*
790821
* The LRU pack is the one with the oldest MRU window, preferring packs
791822
* with no used windows, or the oldest mtime if it has no windows allocated.
@@ -853,12 +884,8 @@ static int close_one_pack(void)
853884
find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse);
854885
}
855886

856-
if (lru_p) {
857-
close(lru_p->pack_fd);
858-
pack_open_fds--;
859-
lru_p->pack_fd = -1;
860-
return 1;
861-
}
887+
if (lru_p)
888+
return close_pack_fd(lru_p);
862889

863890
return 0;
864891
}
@@ -898,12 +925,7 @@ void free_pack_by_name(const char *pack_name)
898925
p = *pp;
899926
if (strcmp(pack_name, p->pack_name) == 0) {
900927
clear_delta_base_cache();
901-
close_pack_windows(p);
902-
if (p->pack_fd != -1) {
903-
close(p->pack_fd);
904-
pack_open_fds--;
905-
}
906-
close_pack_index(p);
928+
close_pack(p);
907929
free(p->bad_object_sha1);
908930
*pp = p->next;
909931
if (last_found_pack == p)
@@ -1037,11 +1059,7 @@ static int open_packed_git(struct packed_git *p)
10371059
{
10381060
if (!open_packed_git_1(p))
10391061
return 0;
1040-
if (p->pack_fd != -1) {
1041-
close(p->pack_fd);
1042-
pack_open_fds--;
1043-
p->pack_fd = -1;
1044-
}
1062+
close_pack_fd(p);
10451063
return -1;
10461064
}
10471065

@@ -1107,11 +1125,8 @@ unsigned char *use_pack(struct packed_git *p,
11071125
p->pack_name,
11081126
strerror(errno));
11091127
if (!win->offset && win->len == p->pack_size
1110-
&& !p->do_not_close) {
1111-
close(p->pack_fd);
1112-
pack_open_fds--;
1113-
p->pack_fd = -1;
1114-
}
1128+
&& !p->do_not_close)
1129+
close_pack_fd(p);
11151130
pack_mmap_calls++;
11161131
pack_open_windows++;
11171132
if (pack_mapped > peak_pack_mapped)

t/t5700-clone-reference.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,5 +188,26 @@ test_expect_success 'clone and dissociate from reference' '
188188
test_must_fail git -C R fsck &&
189189
git -C S fsck
190190
'
191+
test_expect_success 'clone, dissociate from partial reference and repack' '
192+
rm -fr P Q R &&
193+
git init P &&
194+
(
195+
cd P &&
196+
test_commit one &&
197+
git repack &&
198+
test_commit two &&
199+
git repack
200+
) &&
201+
git clone --bare P Q &&
202+
(
203+
cd P &&
204+
git checkout -b second &&
205+
test_commit three &&
206+
git repack
207+
) &&
208+
git clone --bare --dissociate --reference=P Q R &&
209+
ls R/objects/pack/*.pack >packs.txt &&
210+
test_line_count = 1 packs.txt
211+
'
191212

192213
test_done

0 commit comments

Comments
 (0)