# [PATCH] Remove empty directories when checking out a commit with fewer submodules

5 messages from 2010-01-11 to 2010-01-11. Participants: Peter Collingbourne, Johannes Schindelin, Johan Herland, Junio C Hamano.
Thread: https://gitlist.dev/t/22160

## Peter Collingbourne, 2010-01-11 02:59

Subject: [PATCH] Remove empty directories when checking out a commit with fewer submodules
Message-ID: <1263178794-3140-1-git-send-email-peter@pcc.me.uk>
URL: https://gitlist.dev/e/1263178794-3140-1-git-send-email-peter%40pcc.me.uk

```
Change the unlink_entry function to use rmdir to remove submodule
directories.  Currently we try to use unlink, which will never succeed.

Of course rmdir will only succeed for empty (i.e. not checked out)
submodule directories.  Behaviour if a submodule is checked out stays
essentially the same: print a warning message and keep the submodule
directory.

Signed-off-by: Peter Collingbourne <peter@pcc.me.uk>
---
 t/t7400-submodule-basic.sh |    9 +++++++++
 unpack-trees.c             |   12 ++++++++++--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index a0cc99a..1a4dc5f 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -299,6 +299,15 @@ test_expect_success 'ls-files gracefully handles trailing slash' '
 
 '
 
+test_expect_success 'moving to a commit without submodule does not leave empty dir' '
+	rm -rf init &&
+	mkdir init &&
+	git reset --hard &&
+	git checkout initial &&
+	test ! -d init &&
+	git checkout second
+'
+
 test_expect_success 'submodule <invalid-path> warns' '
 
 	git submodule no-such-submodule 2> output.err &&
diff --git a/unpack-trees.c b/unpack-trees.c
index dd5999c..b69847d 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -61,8 +61,16 @@ static void unlink_entry(struct cache_entry *ce)
 {
 	if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce)))
 		return;
-	if (unlink_or_warn(ce->name))
-		return;
+	if (S_ISGITLINK(ce->ce_mode)) {
+		if (rmdir(ce->name)) {
+			warning("unable to rmdir %s: %s",
+				ce->name, strerror(errno));
+			return;
+		}
+	}
+	else
+		if (unlink_or_warn(ce->name))
+			return;
 	schedule_dir_for_removal(ce->name, ce_namelen(ce));
 }
 
-- 
1.6.5

```

## Johannes Schindelin, 2010-01-11 08:57

Subject: Re: [PATCH] Remove empty directories when checking out a commit with fewer submodules
Message-ID: <alpine.DEB.1.00.1001110954410.4985@pacific.mpi-cbg.de>
URL: https://gitlist.dev/e/alpine.DEB.1.00.1001110954410.4985%40pacific.mpi-cbg.de
In-Reply-To: <1263178794-3140-1-git-send-email-peter@pcc.me.uk>

```
Hi,

On Mon, 11 Jan 2010, Peter Collingbourne wrote:

> Change the unlink_entry function to use rmdir to remove submodule
> directories.

NAK.  We should not even try to _unlink_ submodule subdirectories; it 
would be _way_ too easy to lose data that way.  Remember, submodules are a 
totally different beast from regular files.  They can contain valuable, 
yet uncommitted data, that is not even meant to be committed.

So you say if the submodule directories are empty, it is safe?  Not so.  
They will never be empty: there is always .git/, and _that_ can contain 
valuable information that you do not want to throw away, too.  Think of 
unpushed branches, for example.  That would be _fatal_ if you rmdir() that 
for me.

So please, no,
Dscho

```

## Johan Herland, 2010-01-11 09:32

Subject: Re: [PATCH] Remove empty directories when checking out a commit with fewer submodules
Message-ID: <201001111032.45637.johan@herland.net>
URL: https://gitlist.dev/e/201001111032.45637.johan%40herland.net
In-Reply-To: <alpine.DEB.1.00.1001110954410.4985@pacific.mpi-cbg.de>

```
On Monday 11 January 2010, Johannes Schindelin wrote:
> Hi,
>
> On Mon, 11 Jan 2010, Peter Collingbourne wrote:
> > Change the unlink_entry function to use rmdir to remove submodule
> > directories.
>
> NAK.  We should not even try to _unlink_ submodule subdirectories; it
> would be _way_ too easy to lose data that way.  Remember, submodules
> are a totally different beast from regular files.  They can contain
> valuable, yet uncommitted data, that is not even meant to be
> committed.
>
> So you say if the submodule directories are empty, it is safe?  Not
> so. They will never be empty: there is always .git/, and _that_ can
> contain valuable information that you do not want to throw away, too.
>  Think of unpushed branches, for example.  That would be _fatal_ if
> you rmdir() that for me.
>
> So please, no,

I believe what Peter is referring to is the _empty_ directories (and 
that includes no .git/) that are placeholders for submodules that are 
deliberately not cloned/checked out. This lets you do things like:

	git clone url:to/some/project
	cd project
	git checkout some-other-branch-with-different-submodules
	git submodule update --init

Of course, once you clone/checkout a submodule, there will be contents 
in that directory (including the .git/), and Git should not try to 
remove it.


Have fun! :)

...Johan



-- 
Johan Herland, <johan@herland.net>
www.herland.net

```

## Johannes Schindelin, 2010-01-11 09:45

Subject: Re: [PATCH] Remove empty directories when checking out a commit with fewer submodules
Message-ID: <alpine.DEB.1.00.1001111044140.4985@pacific.mpi-cbg.de>
URL: https://gitlist.dev/e/alpine.DEB.1.00.1001111044140.4985%40pacific.mpi-cbg.de
In-Reply-To: <201001111032.45637.johan@herland.net>

```
Hi,

On Mon, 11 Jan 2010, Johan Herland wrote:

> On Monday 11 January 2010, Johannes Schindelin wrote:
> > Hi,
> >
> > On Mon, 11 Jan 2010, Peter Collingbourne wrote:
> > > Change the unlink_entry function to use rmdir to remove submodule
> > > directories.
> >
> > NAK.  We should not even try to _unlink_ submodule subdirectories; it
> > would be _way_ too easy to lose data that way.  Remember, submodules
> > are a totally different beast from regular files.  They can contain
> > valuable, yet uncommitted data, that is not even meant to be
> > committed.
> >
> > So you say if the submodule directories are empty, it is safe?  Not
> > so. They will never be empty: there is always .git/, and _that_ can
> > contain valuable information that you do not want to throw away, too.
> >  Think of unpushed branches, for example.  That would be _fatal_ if
> > you rmdir() that for me.
> >
> > So please, no,
> 
> I believe what Peter is referring to is the _empty_ directories (and 
> that includes no .git/) that are placeholders for submodules that are 
> deliberately not cloned/checked out. This lets you do things like:
> 
> 	git clone url:to/some/project
> 	cd project
> 	git checkout some-other-branch-with-different-submodules
> 	git submodule update --init
> 
> Of course, once you clone/checkout a submodule, there will be contents 
> in that directory (including the .git/), and Git should not try to 
> remove it.

Yes, this might very well have been my confusion.  Peter, could you please 
refer to such submodules as "uninitialized" rather than "empty" in the 
future?  This would help simple minds like mine to understand you better.

Ciao,
Dscho

```

## Junio C Hamano, 2010-01-11 09:53

Subject: Re: [PATCH] Remove empty directories when checking out a commit with fewer submodules
Message-ID: <7vocl1t1b8.fsf@alter.siamese.dyndns.org>
URL: https://gitlist.dev/e/7vocl1t1b8.fsf%40alter.siamese.dyndns.org
In-Reply-To: <alpine.DEB.1.00.1001110954410.4985@pacific.mpi-cbg.de>

```
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> NAK.  We should not even try to _unlink_ submodule subdirectories; it 
> would be _way_ too easy to lose data that way.  Remember, submodules are a 
> totally different beast from regular files.  They can contain valuable, 
> yet uncommitted data, that is not even meant to be committed.
>
> So you say if the submodule directories are empty, it is safe?  Not so.  
> They will never be empty: there is always .git/...

NACK on NAK.

Don't worry, your data will be safe.  The only case rmdir would actually
remove it is (1) you check out superproject that has submodule A, but you
choose not to "submodule init/update" it, because you don't need a
checkout of that part of the tree for your job, and then (2) you switch to
a different version of the superproject that doesn't anymore (or didn't
back then) have that submodule.  In such a use case, you will have only an
empty directory for A in step (1).  The unnecessary empty directory A will
be left behind, even after switching to a version that shouldn't have the
directory there in step (2), if you do not rmdir it.  So the patch is a
strict bugfix (it attempted to unlink, which is a bug; it really meant
"rmdir" and not "rm -rf" which you seem to be worried about).

It is a separate matter to _enhance_ the codepath to actually either (A)
refuse to overwrite (if the version of the superproject you are switching
to in step (2) had a regular file or a directory that is part of the
superproject there, and/or (B) move it away to somewhere safe (recall the
discussion of ".git/modules/$submodule" hierarchy of the superproject?)
automatically when it will disappear.  Such enhancements will help people
who _do_ "submodule init/update" the submodule in step (1) and switch to a
version of the superproject that lacks it in step (2).

```
