From: Anders Melchiorsen <hidden> Date: 2016-06-15 22:45:24
I got an empty directory left over today, and have reduced the problem
to this sequence. If I leave out the second add (so the merge is a
fast forward), the directory is removed as I would expect.
This is with Git 1.6.0.2.
Anders
and@dylle:~$ mkdir repo ; cd repo
and@dylle:~/repo$ git init
Initialized empty Git repository in /home/and/repo/.git/
and@dylle:~/repo$ mkdir a ; date >a/b ; git add a/b ; git commit -m'Add 1'
Created initial commit 72194c7: Add 1
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 a/b
and@dylle:~/repo$ git checkout -b other
Switched to a new branch "other"
and@dylle:~/repo$ git rm a/b ; git commit -m'Remove 1'
rm 'a/b'
Created commit 9c0282c: Remove 1
1 files changed, 0 insertions(+), 1 deletions(-)
delete mode 100644 a/b
and@dylle:~/repo$ git checkout master
Switched to branch "master"
and@dylle:~/repo$ date >c ; git add c ; git commit -m'Add 2'
Created commit 39d60d4: Add 2
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 c
and@dylle:~/repo$ git merge other
Removed a/b
Merge made by recursive.
a/b | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
delete mode 100644 a/b
and@dylle:~/repo$ rmdir a
and@dylle:~/repo$ rmdir a
rmdir: failed to remove `a': No such file or directory
From: Alex Riesen <hidden> Date: 2016-06-15 22:45:24
The code was actually supposed to do that, but was accidentally broken.
Noticed by Anders Melchiorsen.
Signed-off-by: Alex Riesen <redacted>
---
Anders Melchiorsen, Wed, Sep 24, 2008 18:32:22 +0200:
I got an empty directory left over today, and have reduced the problem
to this sequence. If I leave out the second add (so the merge is a
fast forward), the directory is removed as I would expect.
Ach, an old bug. Thanks for reminding!
builtin-merge-recursive.c | 4 +---
t/t3030-merge-recursive.sh | 11 +++++++++++
2 files changed, 12 insertions(+), 3 deletions(-)
From: Alex Riesen <hidden> Date: 2016-06-15 22:45:24
Signed-off-by: Alex Riesen <redacted>
---
While at it, could we cleanup the remove_file routines a little?
builtin-merge-recursive.c | 8 +++-----
1 files changed, 3 insertions(+), 5 deletions(-)
From: Alex Riesen <hidden> Date: 2016-06-15 22:45:24
Actually, just replace it with the one from builtin-merge-recursive.c,
except for ignoring ENOENT error.
Signed-off-by: Alex Riesen <redacted>
---
It is the same as in merge-recursive, but they're so small so unless
we get a special file with such random routines there is no much point
exporting it. Actually, we do seem to have such a file: dir.c. It is
already plagued by file_exists kind of things, why not remove_path...
builtin-rm.c | 24 ++++++++++--------------
1 files changed, 10 insertions(+), 14 deletions(-)
@@ -31,22 +31,18 @@ static void add_list(const char *name)staticintremove_file(constchar*name){-intret;-char*slash;--ret=unlink(name);-if(ret&&errno==ENOENT)-/* The user has removed it from the filesystem by hand */-ret=errno=0;--if(!ret&&(slash=strrchr(name,'/'))){-char*n=xstrdup(name);-do{-n[slash-name]=0;-name=n;-}while(!rmdir(name)&&(slash=strrchr(name,'/')));+char*slash,*dirs;++if(unlink(name)&&errno!=ENOENT)+return-1;+dirs=xstrdup(name);+while((slash=strrchr(name,'/'))){+*slash='\0';+if(rmdir(name)!=0)+break;}-returnret;+free(dirs);+return0;}staticintcheck_local_mod(unsignedchar*head,intindex_only)
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:45:24
Alex Riesen [off-list ref] wrote:
It is the same as in merge-recursive, but they're so small so unless
we get a special file with such random routines there is no much point
exporting it. Actually, we do seem to have such a file: dir.c. It is
already plagued by file_exists kind of things, why not remove_path...
Yea. I'm thinking remove_path should migrate to dir.c. Hell,
we already have rm -rf as remove_dir_recursively() in dir.c.
remove_path is its long-lost soul mate. I'm not applying this
builtin-rm fix, and am hoping you'll rewrite it around a move
of remove_path to dir.c... ;-)
From: Alex Riesen <hidden> Date: 2016-06-15 22:45:24
The function has two potential users which both managed to get wrong
their implementations (the one in builtin-rm.c one has a memleak, and
builtin-merge-recursive.c scribles over its const argument).
Signed-off-by: Alex Riesen <redacted>
---
Shawn O. Pearce, Fri, Sep 26, 2008 17:28:23 +0200:
Alex Riesen [off-list ref] wrote:
quoted
It is the same as in merge-recursive, but they're so small so unless
we get a special file with such random routines there is no much point
exporting it. Actually, we do seem to have such a file: dir.c. It is
already plagued by file_exists kind of things, why not remove_path...
Yea. I'm thinking remove_path should migrate to dir.c. Hell,
we already have rm -rf as remove_dir_recursively() in dir.c.
remove_path is its long-lost soul mate. I'm not applying this
builtin-rm fix, and am hoping you'll rewrite it around a move
of remove_path to dir.c... ;-)
Okay :) The next one is on top of the previous fix in merge-recursive
(removes ENOENT conditional)
dir.c | 20 ++++++++++++++++++++
dir.h | 3 +++
2 files changed, 23 insertions(+), 0 deletions(-)
@@ -81,4 +81,7 @@ extern int is_inside_dir(const char *dir);externvoidsetup_standard_excludes(structdir_struct*dir);externintremove_dir_recursively(structstrbuf*path,intonly_empty);+/* tries to remove the path with empty directories along it, ignores ENOENT */+externintremove_path(constchar*path);+#endif
From: Alex Riesen <hidden> Date: 2016-06-15 22:45:24
Besides, it fixes a memleak (builtin-rm.c) and accidental change of
the input const argument (builtin-merge-recursive.c).
Signed-off-by: Alex Riesen <redacted>
---
Alex Riesen, Sat, Sep 27, 2008 00:56:45 +0200:
quoted
remove_path is its long-lost soul mate. I'm not applying this
builtin-rm fix, and am hoping you'll rewrite it around a move
of remove_path to dir.c... ;-)
Okay :) The next one is on top of the previous fix in merge-recursive
(removes ENOENT conditional)
@@ -29,26 +29,6 @@ static void add_list(const char *name)list.name[list.nr++]=name;}-staticintremove_file(constchar*name)-{-intret;-char*slash;--ret=unlink(name);-if(ret&&errno==ENOENT)-/* The user has removed it from the filesystem by hand */-ret=errno=0;--if(!ret&&(slash=strrchr(name,'/'))){-char*n=xstrdup(name);-do{-n[slash-name]=0;-name=n;-}while(!rmdir(name)&&(slash=strrchr(name,'/')));-}-returnret;-}-staticintcheck_local_mod(unsignedchar*head,intindex_only){/* items in list are already sorted in the cache order,