{"thread":{"id":"9443","subject":"[PATCH] checkout_entry: only try to create directories when no file existed there","startedAt":"2007-08-08T21:00:53Z","lastAt":"2007-08-08T22:54:56Z","messageCount":6,"participants":["Johannes Schindelin","Junio C Hamano","David Kastrup"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"50236","messageId":"Pine.LNX.4.64.0708082200240.14781@racer.site","threadId":"9443","inReplyTo":null,"subject":"[PATCH] checkout_entry: only try to create directories when no file existed there","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-08-08T21:00:53Z","receivedAt":"2007-08-08T21:00:53Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nIt is obvious that we do not have to create directories when the file we\nwant to check out already existed.\n\nBesides, it fixes the obscure use case, where you want to track a file which\nis _outside_ of your working tree, by creating a symbolic link to the directory\nit lives in, and adding the file with something like \"git add symlink/file\".\nWithout this patch, \"git checkout symlink/file\" would actually _replace_\n\"symlink\" by a directory of the same name.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n entry.c                     |    8 +++++---\n t/t2007-checkout-symlink.sh |   11 +++++++++++\n 2 files changed, 16 insertions(+), 3 deletions(-)\n\ndiff --git a/entry.c b/entry.c\nindex 0625112..eacdba2 100644\n--- a/entry.c\n+++ b/entry.c\n@@ -223,8 +223,10 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t\n \t\t\t\treturn error(\"%s is a directory\", path);\n \t\t\tremove_subtree(path);\n \t\t}\n-\t} else if (state->not_new)\n-\t\treturn 0;\n-\tcreate_directories(path, state);\n+\t} else {\n+\t\tif (state->not_new)\n+\t\t\treturn 0;\n+\t\tcreate_directories(path, state);\n+\t}\n \treturn write_entry(ce, path, state, 0);\n }\ndiff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh\nindex 0526fce..02224eb 100755\n--- a/t/t2007-checkout-symlink.sh\n+++ b/t/t2007-checkout-symlink.sh\n@@ -47,4 +47,15 @@ test_expect_success 'switch from dir to symlink' '\n \n '\n \n+test_expect_success 'checkout does not replace symlink/file with dir/file' '\n+\tmkdir 123 &&\n+\tln -s 123 abc &&\n+\techo 1 > abc/1 &&\n+\techo 2 > abc/2 &&\n+\techo 3 > abc/3 &&\n+\tgit add abc/? &&\n+\techo 0 > abc/3 &&\n+\tgit checkout abc/3 &&\n+\ttest -h abc\n+'\n test_done\n-- \n1.5.3.rc4.26.g782e\n"},{"id":"50240","messageId":"7v4pj93evc.fsf@assigned-by-dhcp.cox.net","threadId":"9443","inReplyTo":"Pine.LNX.4.64.0708082200240.14781@racer.site","subject":"Re: [PATCH] checkout_entry: only try to create directories when no file existed there","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-08T21:17:43Z","receivedAt":"2007-08-08T21:17:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> It is obvious that we do not have to create directories when the file we\n> want to check out already existed.\n\nIt is not so obvious to me.  In fact I vaguely recall we had\ncomplaint about opposite case where we did not honor a symlink\nto be checked out as a symlink because an earlier branch had it\nas a directory.\n"},{"id":"50242","messageId":"85y7glpvhi.fsf@lola.goethe.zz","threadId":"9443","inReplyTo":"Pine.LNX.4.64.0708082200240.14781@racer.site","subject":"Re: [PATCH] checkout_entry: only try to create directories when no file existed there","fromName":"David Kastrup","fromEmail":"dak@gnu.org","sentAt":"2007-08-08T21:27:53Z","receivedAt":"2007-08-08T21:27:53Z","isPatch":true,"sender":{"key":"dak@gnu.org","avatar":"https://avatars.githubusercontent.com/u/52141349?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> It is obvious that we do not have to create directories when the file we\n> want to check out already existed.\n>\n> Besides, it fixes the obscure use case, where you want to track a\n> file which is _outside_ of your working tree, by creating a symbolic\n> link to the directory it lives in, and adding the file with\n> something like \"git add symlink/file\".  Without this patch, \"git\n> checkout symlink/file\" would actually _replace_ \"symlink\" by a\n> directory of the same name.\n\nUh, when git is tracking symlinks (and it does by default), this is\nquite the correct thing to do.  Of course, it should rather barf with\na merge conflict.  But it has no business following links and doing\npotential damage either outside or inside of the work tree, by\nconfusing the target of a link with the link itself.  For example, I\ncan easily relocate a complete git work tree with \"mv\" in the\ndirectory hierarchy.  Should an update/commit/whatever then start\nwreaking havoc in places that incidentally don't point to the same\nlocation anymore?\n\nMy vote here is emphatically \"no\".  Just maintain the links, not\nwhatever they point to.\n\nI can think of only a single reasonable exception: if the symlink\nitself is _not_ registered (because is has been explicitly entered\ninto a .gitignore file or never added for other reasons), but its\ntarget _has_ been added explicitly _dereferencing_ the symlink.  This\ndifference can only occur with directory symlinks since file symlinks\ncan't be distinguished in this manner from the name of the link\nitself.\n\nIt would be good if somebody brought this to Johannes' attention, even\nif just replying with a quotation: he chose to killfile me.\n\n-- \nDavid Kastrup, Kriemhildstr. 15, 44793 Bochum\n"},{"id":"50245","messageId":"Pine.LNX.4.64.0708082239120.21857@racer.site","threadId":"9443","inReplyTo":"7v4pj93evc.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] checkout_entry: only try to create directories when no file existed there","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-08-08T21:42:27Z","receivedAt":"2007-08-08T21:42:27Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 8 Aug 2007, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > It is obvious that we do not have to create directories when the file we\n> > want to check out already existed.\n> \n> It is not so obvious to me.  In fact I vaguely recall we had\n> complaint about opposite case where we did not honor a symlink\n> to be checked out as a symlink because an earlier branch had it\n> as a directory.\n\nThat case is not affected by my patch, AFAICT.  It only affects the case \nwhen you check out an entry, say \"a/b/c/d/e/f/g\".  If that file already \nexists, we have to remove it, in order to write over it.  That's the \n\"unlink\" which is above the hunk of the diff I sent.\n\nNow, if we have to remove it, we did a stat() before that.  It succeeded.  \nSo we know that \"a/b/c/d/e/f/\" exists.  It might contain some symlinks, \nbut it exists.\n\nSo putting the \"create_directories()\" into the else branch, we avoid doing \nunnecessary work.\n\nCoincidentally, my hackish use case (don't try this at home, kids!) is \nfixed, too.\n\nCiao,\nDscho\n"},{"id":"50256","messageId":"7vejid1wh2.fsf@assigned-by-dhcp.cox.net","threadId":"9443","inReplyTo":"Pine.LNX.4.64.0708082239120.21857@racer.site","subject":"Re: [PATCH] checkout_entry: only try to create directories when no file existed there","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-08T22:40:25Z","receivedAt":"2007-08-08T22:40:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> Now, if we have to remove it, we did a stat() before that.  It succeeded.  \n> So we know that \"a/b/c/d/e/f/\" exists.  It might contain some symlinks, \n> but it exists.\n\nYes, it is exactly the thing.  It might contain a/b/c as symlink\nbut the index does not say a/b/c _IS_ a symlink, and the code\n\"fixes\" that.  Otherwise, you would get inconsistent result from\n\"git checkout\" depending on random symlink you happen to have in\nyour working tree.\n"},{"id":"50258","messageId":"Pine.LNX.4.64.0708082345540.21857@racer.site","threadId":"9443","inReplyTo":"7vejid1wh2.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] checkout_entry: only try to create directories when no file existed there","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-08-08T22:54:56Z","receivedAt":"2007-08-08T22:54:56Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 8 Aug 2007, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > Now, if we have to remove it, we did a stat() before that.  It succeeded.  \n> > So we know that \"a/b/c/d/e/f/\" exists.  It might contain some symlinks, \n> > but it exists.\n> \n> Yes, it is exactly the thing.  It might contain a/b/c as symlink\n> but the index does not say a/b/c _IS_ a symlink, and the code\n> \"fixes\" that.  Otherwise, you would get inconsistent result from\n> \"git checkout\" depending on random symlink you happen to have in\n> your working tree.\n\nAh, I see what you're getting to.\n\nIf user had a symlink called, say \"syml\", to, say $HOME, and now switches \nto a branch which has \"syml/.bash_profile\", then the given code path would \ntry to replace the symlink with a directory.\n\nHmm.\n\nCiao,\nDscho\n"}]}