write-index: check and warn when worktree crosses a filesystem boundary

As we are stopping the discovery for the repository directory at
filesystem boundaries by default, you might find yourself in a
situation like this:

 (1) You have a tarball of some sort; you extract it $there;

     $ mkdir $there && cd $there
     $ tar xf /var/tmp/tarball.tar

 (2) You notice that the filesystem lacks enough free space, and
     move some part (say "images/") to a separate filesystem, and
     bind-mount;

     $ mv images $another/. && rm -fr images && mkdir images
     $ mount --bind $another/images images

 (3) You add everything to start the project;

     $ git init && git add .

     Up to this point it would work just fine, as you are at the
     top of the working tree and there is no need for repository
     discovery.

 (4) Go down to a subdirectory and start futzing;

     $ cd images && gimp naughty.jpg && git add -u

     This will break as the repository discovery will not go up
     outside of the "images" directory.

Help users by making "git add" notice at the step (3) above that
the working tree is spread across multiple filesystems and warn.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Junio C Hamano
2010-04-04 15:40:06 -07:00
parent cf87463e79
commit 52b98a7d2f

View File

@@ -1550,6 +1550,8 @@ int write_index(struct index_state *istate, int newfd)
struct cache_entry **cache = istate->cache;
int entries = istate->cache_nr;
struct stat st;
int first_valid_ent = -1;
int more_than_one_dev;
for (i = removed = extended = 0; i < entries; i++) {
if (cache[i]->ce_flags & CE_REMOVE)
@@ -1572,6 +1574,7 @@ int write_index(struct index_state *istate, int newfd)
if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
return -1;
more_than_one_dev = 0;
for (i = 0; i < entries; i++) {
struct cache_entry *ce = cache[i];
if (ce->ce_flags & CE_REMOVE)
@@ -1580,8 +1583,19 @@ int write_index(struct index_state *istate, int newfd)
ce_smudge_racily_clean_entry(ce);
if (ce_write_entry(&c, newfd, ce) < 0)
return -1;
if (ce_uptodate(ce)) {
if (first_valid_ent < 0)
first_valid_ent = i;
else if (ce->ce_dev != cache[first_valid_ent]->ce_dev)
more_than_one_dev = 1;
}
}
if (more_than_one_dev &&
!git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0))
warning("working tree spans across filesystems but "
"GIT_DISCOVERY_ACROSS_FILESYSTEM is not set.");
/* Write extension data here */
if (istate->cache_tree) {
struct strbuf sb = STRBUF_INIT;