Skip to content

Commit

Permalink
Merge branch 'js/clone-dissociate'
Browse files Browse the repository at this point in the history
"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`
  • Loading branch information
Junio C Hamano committed Oct 15, 2015
2 parents b80dd55 + 786b150 commit db5adf2
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 23 deletions.
4 changes: 3 additions & 1 deletion builtin/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,8 +1071,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
transport_unlock_pack(transport);
transport_disconnect(transport);

if (option_dissociate)
if (option_dissociate) {
close_all_packs();
dissociate_from_references();
}

junk_mode = JUNK_LEAVE_REPO;
err = checkout();
Expand Down
1 change: 1 addition & 0 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,7 @@ extern void close_pack_index(struct packed_git *);

extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *);
extern void close_pack_windows(struct packed_git *);
extern void close_all_packs(void);
extern void unuse_pack(struct pack_window **);
extern void free_pack_by_name(const char *);
extern void clear_delta_base_cache(void);
Expand Down
59 changes: 37 additions & 22 deletions sha1_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,37 @@ void close_pack_windows(struct packed_git *p)
}
}

static int close_pack_fd(struct packed_git *p)
{
if (p->pack_fd < 0)
return 0;

close(p->pack_fd);
pack_open_fds--;
p->pack_fd = -1;

return 1;
}

static void close_pack(struct packed_git *p)
{
close_pack_windows(p);
close_pack_fd(p);
close_pack_index(p);
}

void close_all_packs(void)
{
struct packed_git *p;

for (p = packed_git; p; p = p->next)
if (p->do_not_close)
die("BUG! Want to close pack marked 'do-not-close'");
else
close_pack(p);
}


/*
* The LRU pack is the one with the oldest MRU window, preferring packs
* with no used windows, or the oldest mtime if it has no windows allocated.
Expand Down Expand Up @@ -853,12 +884,8 @@ static int close_one_pack(void)
find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse);
}

if (lru_p) {
close(lru_p->pack_fd);
pack_open_fds--;
lru_p->pack_fd = -1;
return 1;
}
if (lru_p)
return close_pack_fd(lru_p);

return 0;
}
Expand Down Expand Up @@ -898,12 +925,7 @@ void free_pack_by_name(const char *pack_name)
p = *pp;
if (strcmp(pack_name, p->pack_name) == 0) {
clear_delta_base_cache();
close_pack_windows(p);
if (p->pack_fd != -1) {
close(p->pack_fd);
pack_open_fds--;
}
close_pack_index(p);
close_pack(p);
free(p->bad_object_sha1);
*pp = p->next;
if (last_found_pack == p)
Expand Down Expand Up @@ -1037,11 +1059,7 @@ static int open_packed_git(struct packed_git *p)
{
if (!open_packed_git_1(p))
return 0;
if (p->pack_fd != -1) {
close(p->pack_fd);
pack_open_fds--;
p->pack_fd = -1;
}
close_pack_fd(p);
return -1;
}

Expand Down Expand Up @@ -1107,11 +1125,8 @@ unsigned char *use_pack(struct packed_git *p,
p->pack_name,
strerror(errno));
if (!win->offset && win->len == p->pack_size
&& !p->do_not_close) {
close(p->pack_fd);
pack_open_fds--;
p->pack_fd = -1;
}
&& !p->do_not_close)
close_pack_fd(p);
pack_mmap_calls++;
pack_open_windows++;
if (pack_mapped > peak_pack_mapped)
Expand Down
21 changes: 21 additions & 0 deletions t/t5700-clone-reference.sh
Original file line number Diff line number Diff line change
Expand Up @@ -188,5 +188,26 @@ test_expect_success 'clone and dissociate from reference' '
test_must_fail git -C R fsck &&
git -C S fsck
'
test_expect_success 'clone, dissociate from partial reference and repack' '
rm -fr P Q R &&
git init P &&
(
cd P &&
test_commit one &&
git repack &&
test_commit two &&
git repack
) &&
git clone --bare P Q &&
(
cd P &&
git checkout -b second &&
test_commit three &&
git repack
) &&
git clone --bare --dissociate --reference=P Q R &&
ls R/objects/pack/*.pack >packs.txt &&
test_line_count = 1 packs.txt
'

test_done

0 comments on commit db5adf2

Please sign in to comment.