From: Junio C Hamano <hidden> Date: 2016-06-15 22:44:39
I consider the first one is not part of the series but a bugfix.
The remainder is to teach "git checkout" not to punt in the middle once it
has started touching the work tree.
It does _not_ attempt to autorename a file whose name is NUL to something
else. Partly because I personally think that sort of magic (or "a cute
hack") makes the system unnecessarily complex and fragile while not adding
much to the usability, but more importantly because I do not think we are
ready to adopt that kind of complexity yet, before fixing more basic issue
like this series addresses.
[PATCH 1/5] "git checkout -- paths..." should error out when paths cannot be written
[PATCH 2/5] checkout: make reset_clean_to_new() not die by itself
[PATCH 3/5] checkout: consolidate reset_{to_new,clean_to_new|()
[PATCH 4/5] unpack_trees(): allow callers to differentiate worktree errors from merge errors
[PATCH 5/5] checkout: "best effort" checkout
[PATCH 6/5] NUL hack to create_file()
From: Junio C Hamano <hidden> Date: 2016-06-15 22:44:39
When "git checkout -- paths..." cannot update work tree for whatever
reason, checkout_entry() correctly issued an error message for the path to
the end user, but the command ignored the error, causing the entire
command to succeed. This fixes it.
Signed-off-by: Junio C Hamano <redacted>
---
builtin-checkout.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
@@ -84,6 +84,7 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec)unsignedcharrev[20];intflag;structcommit*head;+interrs=0;intnewfd;structlock_file*lock_file=xcalloc(1,sizeof(structlock_file));
@@ -106,13 +107,14 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec)if(report_path_error(ps_matched,pathspec,0))return1;+/* Now we are committed to check them out */memset(&state,0,sizeof(state));state.force=1;state.refresh_cache=1;for(pos=0;pos<active_nr;pos++){structcache_entry*ce=active_cache[pos];if(pathspec_match(pathspec,NULL,ce->name,0)){-checkout_entry(ce,&state,NULL);+errs|=checkout_entry(ce,&state,NULL);}}
@@ -123,7 +125,8 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec)resolve_ref("HEAD",rev,0,&flag);head=lookup_commit_reference_gently(rev,1);-returnpost_checkout_hook(head,head,0);+errs|=post_checkout_hook(head,head,0);+returnerrs;}staticvoidshow_local_changes(structobject*head)
From: Junio C Hamano <hidden> Date: 2016-06-15 22:44:39
These two were very similar functions with only tiny bit of difference.
Signed-off-by: Junio C Hamano <redacted>
---
* This may be a bit hard to read but "struct checkout_opts" is moved up
at the same time as it is passed to the consolidated function as its
parameter.
builtin-checkout.c | 50 +++++++++++++++-----------------------------------
1 files changed, 15 insertions(+), 35 deletions(-)
@@ -193,16 +183,6 @@ static int reset_clean_to_new(struct tree *tree, int quiet)return0;}-structcheckout_opts{-intquiet;-intmerge;-intforce;--char*new_branch;-intnew_branch_log;-enumbranch_tracktrack;-};-structbranch_info{constchar*name;/* The short name used */constchar*path;/* The full name of a real branch */
@@ -227,7 +207,7 @@ static int merge_working_tree(struct checkout_opts *opts,read_cache();if(opts->force){-ret=reset_to_new(new->commit->tree,opts->quiet);+ret=reset_tree(new->commit->tree,opts,1);if(ret)returnret;}else{
@@ -291,12 +271,12 @@ static int merge_working_tree(struct checkout_opts *opts,add_files_to_cache(NULL,NULL,0);work=write_tree_from_memory();-ret=reset_to_new(new->commit->tree,opts->quiet);+ret=reset_tree(new->commit->tree,opts,1);if(ret)returnret;merge_trees(new->commit->tree,work,old->commit->tree,new->name,"local",&result);-ret=reset_clean_to_new(new->commit->tree,opts->quiet);+ret=reset_tree(new->commit->tree,opts,0);if(ret)returnret;}
From: Junio C Hamano <hidden> Date: 2016-06-15 22:44:39
When unpack_trees() returned an error while switching branches, we used to
stop right there, exiting without writing the index out or switching HEAD.
This is Ok when unpack_trees() detected a locally modified paths or
untracked files that could be overwritten by branch switching, but it is
undesirable if unpack_trees() already committed to update the work tree
and a failure is returned because some but not all paths are updated
(perhaps a directory that some files need to go in was made read-only by
mistake, or a file that will be overwritten by branch switching had a
mandatory lock on it and we could not unlink).
This changes the behaviour upon such an error to complete the branch
switching; the files updated in the work tree will hopefully much more
consistent with the index and HEAD derived from the switched-to branch.
We still issue error messages, and exit the command with non-zero status,
so scripted callers need to notice it.
Signed-off-by: Junio C Hamano <redacted>
---
builtin-checkout.c | 22 ++++++++++++++++++----
1 files changed, 18 insertions(+), 4 deletions(-)
@@ -178,9 +179,20 @@ static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree)opts.dst_index=&the_index;parse_tree(tree);init_tree_desc(&tree_desc,tree->buffer,tree->size);-if(unpack_trees(1,&tree_desc,&opts))+switch(unpack_trees(1,&tree_desc,&opts)){+case-2:+o->writeout_error=1;+/*+*Wereturn0nevertheless,astheindexisallright+*andmoreimportantlywehavemadebesteffortsto+*updatepathsintheworktree,andwecannotrevert+*them.+*/+case0:+return0;+default:return128;-return0;+}}structbranch_info{
@@ -243,7 +255,8 @@ static int merge_working_tree(struct checkout_opts *opts,tree=parse_tree_indirect(new->commit->object.sha1);init_tree_desc(&trees[1],tree->buffer,tree->size);-if(unpack_trees(2,trees,&topts)){+ret=unpack_trees(2,trees,&topts);+if(ret==-1){/**Unpackcouldn'tdoatrivialmerge;either*giveupordoarealmerge,dependingon
From: Junio C Hamano <hidden> Date: 2016-06-15 22:44:39
Instead of uniformly returning -1 on any error, this teaches
unpack_trees() to return -2 when the merge itself is Ok but worktree
refuses to get updated.
Signed-off-by: Junio C Hamano <redacted>
---
unpack-trees.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
From: Junio C Hamano <hidden> Date: 2016-06-15 22:44:39
This is not meant for application to the mainline. It allows your git to
refuse to create a blob whose name is "nul".
---
entry.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
From: Junio C Hamano <hidden> Date: 2016-06-15 22:44:39
Instead, have its error percolate up through the callchain and let it be
the exit status of the main command. No semantic changes yet.
Signed-off-by: Junio C Hamano <redacted>
---
builtin-checkout.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
@@ -172,7 +172,7 @@ static int reset_to_new(struct tree *tree, int quiet)return0;}-staticvoidreset_clean_to_new(structtree*tree,intquiet)+staticintreset_clean_to_new(structtree*tree,intquiet){structunpack_trees_optionsopts;structtree_desctree_desc;
@@ -189,7 +189,8 @@ static void reset_clean_to_new(struct tree *tree, int quiet)parse_tree(tree);init_tree_desc(&tree_desc,tree->buffer,tree->size);if(unpack_trees(1,&tree_desc,&opts))-exit(128);+return128;+return0;}structcheckout_opts{
@@ -295,7 +296,9 @@ static int merge_working_tree(struct checkout_opts *opts,returnret;merge_trees(new->commit->tree,work,old->commit->tree,new->name,"local",&result);-reset_clean_to_new(new->commit->tree,opts->quiet);+ret=reset_clean_to_new(new->commit->tree,opts->quiet);+if(ret)+returnret;}}
From: Johannes Sixt <hidden> Date: 2016-06-15 22:44:39
Junio C Hamano schrieb:
This is not meant for application to the mainline. It allows your git to
refuse to create a blob whose name is "nul".
It's not just about "nul"; these won't work either: "aux", "prn", "con",
"com\d+", "lpt\d+", neither do "$one_of_these.$some_extension". And all of
that regardless of the case!
See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
Definitely, we don't ever want to have such special-casing somewhere in git.
-- Hannes
From: Marius Storm-Olsen <hidden> Date: 2016-06-15 22:44:39
Johannes Sixt said the following on 29.05.2008 08:33:
Junio C Hamano schrieb:
quoted
This is not meant for application to the mainline. It allows your git to
refuse to create a blob whose name is "nul".
It's not just about "nul"; these won't work either: "aux", "prn", "con",
"com\d+", "lpt\d+", neither do "$one_of_these.$some_extension". And all of
that regardless of the case!
See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
Definitely, we don't ever want to have such special-casing somewhere in git.
They _can_ be used by using the UNC notation:
\\?\<drive letter>:\<path>\nul
Do you think we should special-case that, or simply fail?
( 9:04:57 - D:\home\marius\source\hg\test)
> hg checkout
abort: The parameter is incorrect: D:\home\marius\source\hg\test\nul
'Nuff said? :-)
--
.marius [@trolltech.com]
'if you know what you're doing, it's not research'
From: Johannes Sixt <hidden> Date: 2016-06-15 22:44:39
Marius Storm-Olsen schrieb:
Johannes Sixt said the following on 29.05.2008 08:33:
quoted
Junio C Hamano schrieb:
quoted
This is not meant for application to the mainline. It allows your
git to
refuse to create a blob whose name is "nul".
It's not just about "nul"; these won't work either: "aux", "prn", "con",
"com\d+", "lpt\d+", neither do "$one_of_these.$some_extension". And
all of
that regardless of the case!
See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
Definitely, we don't ever want to have such special-casing somewhere
in git.
They _can_ be used by using the UNC notation:
\\?\<drive letter>:\<path>\nul
Do you think we should special-case that, or simply fail?
Rhetoric question: What's so special about those files?
"foo/nul" is a file you don't have permissions to write to. Period. We
should fail the same way as if you had 'chmod a-w foo/nul foo', or as if
there's a bad sector on the disk. Junio's patch series is the way to go
(without 6/5, of course).
-- Hannes
From: Johannes Schindelin <hidden> Date: 2016-06-15 22:44:39
Hi,
On Thu, 29 May 2008, Johannes Sixt wrote:
Junio C Hamano schrieb:
quoted
This is not meant for application to the mainline. It allows your git
to refuse to create a blob whose name is "nul".
It's not just about "nul"; these won't work either: "aux", "prn", "con",
"com\d+", "lpt\d+", neither do "$one_of_these.$some_extension". And all
of that regardless of the case!
See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
Definitely, we don't ever want to have such special-casing somewhere in
git.
I think that the standard methods, namely checking by hook, should be good
enough.
Ciao,
Dscho
Shouldn't this be EEXIST? I think the issue is that the first exists for
the purpose of open() but not for anything else we've done up to this
point.
+ return -1;
+ }
+ }
mode = (mode & 0100) ? 0777 : 0666;
return open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
}
--
1.5.6.rc0.43.g823ea
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Daniel Barkalow <hidden> Date: 2016-06-15 22:44:39
On Thu, 29 May 2008, Marius Storm-Olsen wrote:
Johannes Sixt said the following on 29.05.2008 08:33:
quoted
Junio C Hamano schrieb:
quoted
This is not meant for application to the mainline. It allows your git to
refuse to create a blob whose name is "nul".
It's not just about "nul"; these won't work either: "aux", "prn", "con",
"com\d+", "lpt\d+", neither do "$one_of_these.$some_extension". And all of
that regardless of the case!
See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
Definitely, we don't ever want to have such special-casing somewhere in git.
They _can_ be used by using the UNC notation:
\\?\<drive letter>:\<path>\nul
Do you think we should special-case that, or simply fail?
Perhaps we should see if we can get an open() that always uses that
notation for the actual system call? I doubt we want to support the
DOS-ish meanings even if the user provides them as input sources. If it's
not actually a problem with the underlying storage mechanism, but rather a
flaw in the POSIX implementation for Windows, we should fix that (or do
something in compat to work around it) instead of failing in any way to
support it in git. Of course, people on Windows using projects with these
filenames will probably run into problems with other tools, but at least
git will behave properly.
On the other hand, I bet there are going to be real issues with filenames
with backslashes in them.
-Daniel
*This .sig left intentionally blank*
From: Brian Dessent <hidden> Date: 2016-06-15 22:44:39
Daniel Barkalow wrote:
support it in git. Of course, people on Windows using projects with these
filenames will probably run into problems with other tools, but at least
git will behave properly.
I don't see how it would help to have core git using the Native syntax
to bypass the Win32 layer's restrictions but none of the accompanying
suite of tools, i.e. the dozens of various MSYS sh.exe, perl.exe,
cat.exe, etc. None of those would be able to open or even delete those
files with the reserved filenames.
Users tend to get upset when software creates files that cannot be
removed through conventional methods, e.g. Explorer is completely
powerless to remove it. Cygwin shipped with a bug several years ago
that unintentionally allowed to create (but not unlink) reserved
filenames. Unless you knew the magical incantation of "del
\\.\c:\path\to\nul" the file was immutable.
Brian
From: Daniel Barkalow <hidden> Date: 2016-06-15 22:44:39
On Thu, 29 May 2008, Brian Dessent wrote:
Daniel Barkalow wrote:
quoted
support it in git. Of course, people on Windows using projects with these
filenames will probably run into problems with other tools, but at least
git will behave properly.
I don't see how it would help to have core git using the Native syntax
to bypass the Win32 layer's restrictions but none of the accompanying
suite of tools, i.e. the dozens of various MSYS sh.exe, perl.exe,
cat.exe, etc. None of those would be able to open or even delete those
files with the reserved filenames.
Users tend to get upset when software creates files that cannot be
removed through conventional methods, e.g. Explorer is completely
powerless to remove it. Cygwin shipped with a bug several years ago
that unintentionally allowed to create (but not unlink) reserved
filenames. Unless you knew the magical incantation of "del
\\.\c:\path\to\nul" the file was immutable.
Well, "git rm <filename>" would work. Or "git mv <weird> <okay>", which is
possibly more productive. Or checking out a version that doesn't contain
it. It's a lot worse if the tool that created it can't remove it than if
tools other than the one that created it can't deal with it.
-Daniel
*This .sig left intentionally blank*
From: Mark Levedahl <hidden> Date: 2016-06-15 22:44:39
Junio C Hamano wrote:
[PATCH 1/5] "git checkout -- paths..." should error out when paths cannot be written
[PATCH 2/5] checkout: make reset_clean_to_new() not die by itself
[PATCH 3/5] checkout: consolidate reset_{to_new,clean_to_new|()
[PATCH 4/5] unpack_trees(): allow callers to differentiate worktree errors from merge errors
[PATCH 5/5] checkout: "best effort" checkout
[PATCH 6/5] NUL hack to create_file()
This works! I've added these patches (pulled from pu) to my tree and rebuilt.
The current results on Cygwin...
git>git checkout -f b71ce7f3f13ebd0e
Previous HEAD position was 952538f... checkout: "best effort" checkout
error: git-checkout-index: unable to create file t/t5100/nul (File exists)
HEAD is now at b71ce7f... Merge 1.5.5.3 in
git>git status
# Not currently on any branch.
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: t/t5100/nul
#
no changes added to commit (use "git add" and/or "git commit -a")
git>git mv t/t5100/nul t/t5100/nul-plain
fatal: renaming t/t5100/nul failed: Invalid argument
git>git rm -f --cached t/t5100/nul
rm 't/t5100/nul'
git>git show HEAD:t/t5100/nul
From nobody Mon Sep 17 00:00:00 2001
---
diff --git a/foo b/foo
^Some strange test^^
^@
So, for posterity, git-mv cannot rename the offending file in the index, but the
file can be removed, and its contents piped into a file of non-offending name,
so a reasonable solution for this case exists.
Many thanks to all, especially to Junio for actually creating the fix.
Mark