Commit Graph

981 Commits

Author SHA1 Message Date
Jeff Hostetler
6fa4324438 fsmonitor--daemon: cd out of worktree root
Teach the fsmonitor--daemon to CD outside of the worktree
before starting up.

The common Git startup mechanism causes the CWD of the daemon process
to be in the root of the worktree.  On Windows, this causes the daemon
process to hold a locked handle on the CWD and prevents other
processes from moving or deleting the worktree while the daemon is
running.

CD to HOME before entering main event loops.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:10 +02:00
Jeff Hostetler
7059baba90 compat/fsmonitor/fsm-listen-darwin: ignore FSEvents caused by xattr changes on MacOS
Ignore FSEvents resulting from `xattr` changes.  Git does not care about
xattr's or changes to xattr's, so don't waste time collecting these
events in the daemon nor transmitting them to clients.

Various security tools add xattrs to files and/or directories, such as
to mark them as having been downloaded.  We should ignore these events
since it doesn't affect the content of the file/directory or the normal
meta-data that Git cares about.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:10 +02:00
Jeff Hostetler
e3c9f93317 fsmonitor-settings: remote repos on Windows are incompatible with FSMonitor
Teach Git to detect remote working directories on Windows and mark them as
incompatible with FSMonitor.

With this `git fsmonitor--daemon run` will error out with a message like it
does for bare repos.

Client commands, such as `git status`, will not attempt to start the daemon.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:10 +02:00
Jeff Hostetler
6635d1acfa fsmonitor-settings: remote repos on MacOS are incompatible with FSMonitor
Teach Git to detect remote working directories on MacOS and mark them as
incompatible with FSMonitor.

With this, `git fsmonitor--daemon run` will error out with a message
like it does for bare repos.

Client commands, like `git status`, will not attempt to start the daemon.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:10 +02:00
Jeff Hostetler
c54c767b1a fsmonitor-settings: stub in platform-specific incompatibility checking on MacOS
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:10 +02:00
Jeff Hostetler
d432e98d60 fsmonitor-settings: virtual repos are incompatible with FSMonitor
Virtual repos, such as GVFS (aka VFS for Git), are incompatible
with FSMonitor.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:10 +02:00
Jeff Hostetler
b77197af82 fsmonitor-settings: stub in platform-specific incompatibility checking
Extend generic incompatibility checkout with platform-specific
mechanism.  Stub in Win32 version.

In the existing fsmonitor-settings code we have a way to mark
types of repos as incompatible with fsmonitor (whether via the
hook and ipc APIs).  For example, we do this for bare repos,
since there are no files to watch.

Extend this exclusion mechanism for platfor-specific reasons.
This commit just creates the framework and adds a stub for Win32.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:10 +02:00
Jeff Hostetler
4597bc9a8a compat/fsmonitor/fsm-listen-win32: handle shortnames
Teach FSMonitor daemon on Windows to recognize shortname paths as
aliases of normal longname paths.  FSMonitor clients, such as `git
status`, should receive the longname spelling of changed files (when
possible).

Sometimes we receive FS events using the shortname, such as when a CMD
shell runs "RENAME GIT~1 FOO" or "RMDIR GIT~1".  The FS notification
arrives using whatever combination of long and shortnames were used by
the other process.  (Shortnames do seem to be case normalized,
however.)

Use Windows GetLongPathNameW() to try to map the pathname spelling in
the notification event into the normalized longname spelling.  (This
can fail if the file/directory is deleted, moved, or renamed, because
we are asking the FS for the mapping in response to the event and
after it has already happened, but we try.)

Special case the shortname spelling of ".git" to avoid under-reporting
these events.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:09 +02:00
Jeff Hostetler
38560a3b5a compat/fsmonitor/fsm-listen-darwin: implement FSEvent listener on MacOS
Implement file system event listener on MacOS using FSEvent,
CoreFoundation, and CoreServices.

Co-authored-by: Kevin Willford <Kevin.Willford@microsoft.com>
Co-authored-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:08 +02:00
Jeff Hostetler
7aa75f6b6b compat/fsmonitor/fsm-listen-darwin: add macos header files for FSEvent
Include MacOS system declarations to allow us to use FSEvent and
CoreFoundation APIs.  We need GCC and clang versions because of
compiler and header file conflicts.

While it is quite possible to #include Apple's CoreServices.h when
compiling C source code with clang, trying to build it with GCC
currently fails with this error:

In file included
   from /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/Security.framework/Headers/AuthSession.h:32,
   from /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/Security.framework/Headers/Security.h:42,
   from /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/OSServices.framework/Headers/CSIdentity.h:43,
   from /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/OSServices.framework/Headers/OSServices.h:29,
   from /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Headers/IconsCore.h:23,
   from /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Headers/LaunchServices.h:23,
   from /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreServices.framework/Headers/CoreServices.h:45,
     /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/Security.framework/Headers/Authorization.h:193:7: error: variably modified 'bytes' at file scope
       193 | char bytes[kAuthorizationExternalFormLength];
           |      ^~~~~

The underlying reason is that GCC (rightfully) objects that an `enum`
value such as `kAuthorizationExternalFormLength` is not a constant
(because it is not, the preprocessor has no knowledge of it, only the
actual C compiler does) and can therefore not be used to define the size
of a C array.

This is a known problem and tracked in GCC's bug tracker:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93082

In the meantime, let's not block things and go the slightly ugly route
of declaring/defining the FSEvents constants, data structures and
functions that we need, so that we can avoid above-mentioned issue.

Let's do this _only_ for GCC, though, so that the CI/PR builds (which
build both with clang and with GCC) can guarantee that we _are_ using
the correct data types.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:08 +02:00
Jeff Hostetler
dd378b45fa compat/fsmonitor/fsm-listen-win32: implement FSMonitor backend on Windows
Teach the win32 backend to register a watch on the working tree
root directory (recursively).  Also watch the <gitdir> if it is
not inside the working tree.  And to collect path change notifications
into batches and publish.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:08 +02:00
Jeff Hostetler
c569886157 compat/fsmonitor/fsm-listen-darwin: stub in backend for Darwin
Stub in empty implementation of fsmonitor--daemon
backend for Darwin (aka MacOS).

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:07 +02:00
Jeff Hostetler
3aac461ddf compat/fsmonitor/fsm-listen-win32: stub in backend for Windows
Stub in empty filesystem listener backend for fsmonitor--daemon on Windows.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:07 +02:00
Jeff Hostetler
e3ac087f25 simple-ipc/ipc-win32: add Windows ACL to named pipe
Set an ACL on the named pipe to allow the well-known group EVERYONE
to read and write to the IPC server's named pipe.  In the event that
the daemon was started with elevation, allow non-elevated clients
to communicate with the daemon.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:05 +02:00
Jeff Hostetler
e5a1d91095 simple-ipc/ipc-win32: add trace2 debugging
Create "ipc-debug" category events to log unexpected errors
when creating Simple-IPC connections.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:05 +02:00
Jeff Hostetler
f183cc7b0d simple-ipc: preparations for supporting binary messages.
Add `command_len` argument to the Simple IPC API.

In my original Simple IPC API, I assumed that the request would always
be a null-terminated string of text characters.  The `command`
argument was just a `const char *`.

I found a caller that would like to pass a binary command to the
daemon, so I am amending the Simple IPC API to receive `const char
*command, size_t command_len` arguments.

I considered changing the `command` argument to be a `void *`, but the
IPC layer simply passes it to the pkt-line layer which takes a `const
char *`, so to avoid confusion I left it as is.

Note, the response side has always been a `struct strbuf` which
includes the buffer and length, so we already support returning a
binary answer.  (Yes, it feels a little weird returning a binary
buffer in a `strbuf`, but it works.)

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:05 +02:00
Jeff Hostetler
19ee980052 fixup! simple-ipc: preparations for supporting binary messages.
This reverts commit 15b44c3f21.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:04 +02:00
Jeff Hostetler
c1b76c04bc fixup! fsm-listen-win32: stub in backend for Windows
This reverts commit 1b42506aba.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:04 +02:00
Jeff Hostetler
d953cad8a9 fixup! fsm-listen-darwin: stub in backend for Darwin
This reverts commit a6784cb378.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:03 +02:00
Jeff Hostetler
32c3a207fc fixup! fsm-listen-win32: implement FSMonitor backend on Windows
This reverts commit a25a759709.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:03 +02:00
Jeff Hostetler
6fe4f74050 fixup! fsm-listen-darwin: add macos header files for FSEvent
This reverts commit ccc75e26a1.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:03 +02:00
Jeff Hostetler
b27da829cd fixup! fsm-listen-darwin: implement FSEvent listener on MacOS
This reverts commit 8657519ee5.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:03 +02:00
Jeff Hostetler
0e325759c6 fixup! fsmonitor: handle shortname for .git
This reverts commit 0fadc91ae4.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:02 +02:00
Jeff Hostetler
09f93852e1 fixup! ipc-win32: add trace2 debugging
This reverts commit ddab099c55.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:02 +02:00
Jeff Hostetler
cd4411cb3c fixup! fsmonitor-settings: stub in platform-specific incompatibility checking
This reverts commit 56b6c9aa99.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:01 +02:00
Jeff Hostetler
5a54dfa08a fixup! fsmonitor-settings: virtual repos are incompatible with FSMonitor
This reverts commit 7b37f49707.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:01 +02:00
Jeff Hostetler
627671214f fixup! fsmonitor-settings: stub in platform-specific incompatibility checking on MacOS
This reverts commit 7b8c024f51.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:01 +02:00
Jeff Hostetler
479df9ff68 fixup! fsmonitor-settings: remote repos on MacOS are incompatible with FSMonitor
This reverts commit da396b6298.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:01 +02:00
Jeff Hostetler
98b55c3021 fixup! fsmonitor-settings: remote repos on Windows are incompatible with FSMonitor
This reverts commit a002e816f2.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:40:01 +02:00
Jeff Hostetler
bfa0044ecc fixup! mingw: support long paths
Revert the FSMonitor-related portions of 64da6f2182

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2021-10-02 22:39:47 +02:00
Johannes Schindelin
8735530946 fixup! mingw: support long paths
This change was inadvertently kept in a patch that precedes the
`core.longPaths` support.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-24 00:05:45 +02:00
Johannes Schindelin
2335b45385 Merge yet another fixup
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-24 00:02:05 +02:00
Johannes Schindelin
55d9203386 Merge another fixup
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-24 00:01:26 +02:00
Johannes Schindelin
72648d9205 fixup! mingw: implement a platform-specific strbuf_realpath()
This is needed to let the code compile without error.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-23 23:56:44 +02:00
Johannes Schindelin
7b052e6d20 fixup! mingw: ignore HOMEDRIVE/HOMEPATH if it points to Windows' system directory
The long-paths support comes later in Git for Windows' branch thicket...

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-23 15:24:09 +02:00
Johannes Schindelin
f749f4fc79 Merge pull request #1170 from dscho/mingw-kill-process
Handle Ctrl+C in Git Bash nicely

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:31 +02:00
Johannes Schindelin
cef5020879 Merge branch 'busybox-w32'
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:31 +02:00
Johannes Schindelin
06672392c6 Merge pull request #1897 from piscisaureus/symlink-attr
Specify symlink type in .gitattributes
2021-08-17 00:17:31 +02:00
Johannes Schindelin
4b1d17dac1 mingw: really handle SIGINT
Previously, we did not install any handler for Ctrl+C, but now we really
want to because the MSYS2 runtime learned the trick to call the
ConsoleCtrlHandler when Ctrl+C was pressed.

With this, hitting Ctrl+C while `git log` is running will only terminate
the Git process, but not the pager. This finally matches the behavior on
Linux and on macOS.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:28 +02:00
Johannes Schindelin
9b7249d142 mingw: kill child processes in a gentler way
The TerminateProcess() function does not actually leave the child
processes any chance to perform any cleanup operations. This is bad
insofar as Git itself expects its signal handlers to run.

A symptom is e.g. a left-behind .lock file that would not be left behind
if the same operation was run, say, on Linux.

To remedy this situation, we use an obscure trick: we inject a thread
into the process that needs to be killed and to let that thread run the
ExitProcess() function with the desired exit status. Thanks J Wyman for
describing this trick.

The advantage is that the ExitProcess() function lets the atexit
handlers run. While this is still different from what Git expects (i.e.
running a signal handler), in practice Git sets up signal handlers and
atexit handlers that call the same code to clean up after itself.

In case that the gentle method to terminate the process failed, we still
fall back to calling TerminateProcess(), but in that case we now also
make sure that processes spawned by the spawned process are terminated;
TerminateProcess() does not give the spawned process a chance to do so
itself.

Please note that this change only affects how Git for Windows tries to
terminate processes spawned by Git's own executables. Third-party
software that *calls* Git and wants to terminate it *still* need to make
sure to imitate this gentle method, otherwise this patch will not have
any effect.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:28 +02:00
Johannes Schindelin
daeb0d14ee mingw: Windows Docker volumes are *not* symbolic links
... even if they may look like them.

As looking up the target of the "symbolic link" (just to see whether it
starts with `/ContainerMappedDirectories/`) is pretty expensive, we
do it when we can be *really* sure that there is a possibility that this
might be the case.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: JiSeop Moon <zcube@zcube.kr>
2021-08-17 00:17:26 +02:00
Bert Belder
f116920dc7 mingw: allow to specify the symlink type in .gitattributes
On Windows, symbolic links have a type: a "file symlink" must point at
a file, and a "directory symlink" must point at a directory. If the
type of symlink does not match its target, it doesn't work.

Git does not record the type of symlink in the index or in a tree. On
checkout it'll guess the type, which only works if the target exists
at the time the symlink is created. This may often not be the case,
for example when the link points at a directory inside a submodule.

By specifying `symlink=file` or `symlink=dir` the user can specify what
type of symlink Git should create, so Git doesn't have to rely on
unreliable heuristics.

Signed-off-by: Bert Belder <bertbelder@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:26 +02:00
JiSeop Moon
9e7403b192 mingw: move the file_attr_to_st_mode() function definition
In preparation for making this function a bit more complicated (to allow
for special-casing the `ContainerMappedDirectories` in Windows
containers, which look like a symbolic link, but are not), let's move it
out of the header.

Signed-off-by: JiSeop Moon <zcube@zcube.kr>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:26 +02:00
Johannes Schindelin
55060fa3f3 mingw: emulate stat() a little more faithfully
When creating directories via `safe_create_leading_directories()`, we
might encounter an already-existing directory which is not
readable by the current user. To handle that situation, Git's code calls
`stat()` to determine whether we're looking at a directory.

In such a case, `CreateFile()` will fail, though, no matter what, and
consequently `mingw_stat()` will fail, too. But POSIX semantics seem to
still allow `stat()` to go forward.

So let's call `mingw_lstat()` for the rescue if we fail to get a file
handle due to denied permission in `mingw_stat()`, and fill the stat
info that way.

We need to be careful to not allow this to go forward in case that we're
looking at a symbolic link: to resolve the link, we would still have to
create a file handle, and we just found out that we cannot. Therefore,
`stat()` still needs to fail with `EACCES` in that case.

This fixes https://github.com/git-for-windows/git/issues/2531.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:26 +02:00
Johannes Schindelin
0fb3908161 Introduce helper to create symlinks that knows about index_state
On Windows, symbolic links actually have a type depending on the target:
it can be a file or a directory.

In certain circumstances, this poses problems, e.g. when a symbolic link
is supposed to point into a submodule that is not checked out, so there
is no way for Git to auto-detect the type.

To help with that, we will add support over the course of the next
commits to specify that symlink type via the Git attributes. This
requires an index_state, though, something that Git for Windows'
`symlink()` replacement cannot know about because the function signature
is defined by the POSIX standard and not ours to change.

So let's introduce a helper function to create symbolic links that
*does* know about the index_state.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:26 +02:00
JiSeop Moon
481741d01d mingw: when running in a Windows container, try to rename() harder
It is a known issue that a rename() can fail with an "Access denied"
error at times, when copying followed by deleting the original file
works. Let's just fall back to that behavior.

Signed-off-by: JiSeop Moon <zcube@zcube.kr>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:26 +02:00
Johannes Schindelin
82f50e22d9 mingw: when path_lookup() failed, try BusyBox
BusyBox comes with a ton of applets ("applet" being the identical
concept to Git's "builtins"). And similar to Git's builtins, the applets
can be called via `busybox <command>`, or the BusyBox executable can be
copied/hard-linked to the command name.

The similarities do not end here. Just as with Git's builtins, it is
problematic that BusyBox' hard-linked applets cannot easily be put into
a .zip file: .zip archives have no concept of hard-links and therefore
would store identical copies (and also extract identical copies,
"inflating" the archive unnecessarily).

To counteract that issue, MinGit already ships without hard-linked
copies of the builtins, and the plan is to do the same with BusyBox'
applets: simply ship busybox.exe as single executable, without
hard-linked applets.

To accommodate that, Git is being taught by this commit a very special
trick, exploiting the fact that it is possible to call an executable
with a command-line whose argv[0] is different from the executable's
name: when `sh` is to be spawned, and no `sh` is found in the PATH, but
busybox.exe is, use that executable (with unchanged argv).

Likewise, if any executable to be spawned is not on the PATH, but
busybox.exe is found, parse the output of `busybox.exe --help` to find
out what applets are included, and if the command matches an included
applet name, use busybox.exe to execute it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:26 +02:00
Bert Belder
777c01e832 Win32: symlink: move phantom symlink creation to a separate function
Signed-off-by: Bert Belder <bertbelder@gmail.com>
2021-08-17 00:17:26 +02:00
JiSeop Moon
2b4bf3501e mingw: introduce code to detect whether we're inside a Windows container
This will come in handy in the next commit.

Signed-off-by: JiSeop Moon <zcube@zcube.kr>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:26 +02:00
Johannes Schindelin
7a57834763 mingw: explicitly specify with which cmd to prefix the cmdline
The main idea of this patch is that even if we have to look up the
absolute path of the script, if only the basename was specified as
argv[0], then we should use that basename on the command line, too, not
the absolute path.

This patch will also help with the upcoming patch where we automatically
substitute "sh ..." by "busybox sh ..." if "sh" is not in the PATH but
"busybox" is: we will do that by substituting the actual executable, but
still keep prepending "sh" to the command line.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2021-08-17 00:17:26 +02:00