Skip to content

Commit

Permalink
mingw: respect core.longPaths when initializing a new gitdir
Browse files Browse the repository at this point in the history
Use case:
Allow git to checkout a repository or submodule in a directory with a long
path when core.longpaths = true.

Example:
> ./git.exe config --global core.longpaths true
> ./git.exe clone https://github.com/git/git.git --recurse-submodules \
/c/eval/git_test/loooooooooooooooooooooooooooooooooooooooooooooooooooooooo\
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo\
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo\
oooooooong

Context:
$ sh --version
	GNU bash, version 4.4.23(1)-release (x86_64-pc-msys)
$ ./git.exe --version --build-options
	git version 2.36.1.windows.1
	cpu: x86_64
	built from commit: e2ff68a
	sizeof-long: 4
	sizeof-size_t: 8
	shell-path: /bin/sh
	feature: fsmonitor--daemon

Error:
fatal: '$GIT_DIR' too big.

Problem analysis:
setup_explicit_git_dir in setup.c uses PATH_MAX to check if the git dir is
to long. On Windows PATH_MAX is set by limit.h to 260 and
setup_explicit_git_dir ignores core.longpaths.

Solution:
The implementation is based on the solution proposed by Johannes
Schindelin, see:
#3372 (comment)

* Refactor the part of trace2_initialize() that reads the config.
* Make tr2_sysenv_cb() a public function.
* No longer calling it from trace2_initialize(), but from a static callback
  function in common-main.c.
* Calling read_very_early_config() explicitly in main(), with that static
  callback function that calls into tr2_sysenv_cb().
* Extend the static callback function for Windows, and parse core.longPaths
  in that function.
* Extend startup_info struct in cache.h with 'int max_long_path' so we can
  use it in setup_explicit_git_dir instead of PATH_MAX.

This fixes #3372

Signed-off-by: Kevin Worm <[email protected]>
Signed-off-by: Johannes Schindelin <[email protected]>
  • Loading branch information
kevin-worm authored and dscho committed May 30, 2022
1 parent 3b059de commit 7a3a4c7
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 2 deletions.
5 changes: 4 additions & 1 deletion common-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ static void restore_sigpipe_to_default(void)

static int read_very_early_config_cb(const char *key, const char *value, void *d)
{
return tr2_sysenv_cb(key, value, d);
if (starts_with(key, "core."))
return platform_core_config(key, value, d);
else
return tr2_sysenv_cb(key, value, d);
}

int main(int argc, const char **argv)
Expand Down
6 changes: 6 additions & 0 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,12 @@ int is_valid_win32_path(const char *path, int allow_literal_nul);
*/
int handle_long_path(wchar_t *path, int len, int max_path, int expand);

static inline int mingw_get_max_path_size(void)
{
return core_long_paths ? MAX_LONG_PATH : MAX_PATH;
}
#define get_max_path_size mingw_get_max_path_size

/**
* Converts UTF-8 encoded string to UTF-16LE.
*
Expand Down
4 changes: 4 additions & 0 deletions git-compat-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,10 @@ char *gitdirname(char *);
#define PATH_MAX 4096
#endif

#ifndef get_max_path_size
#define get_max_path_size() PATH_MAX
#endif

typedef uintmax_t timestamp_t;
#define PRItime PRIuMAX
#define parse_timestamp strtoumax
Expand Down
2 changes: 1 addition & 1 deletion setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
char *gitfile;
int offset;

if (PATH_MAX - 40 < strlen(gitdirenv))
if (get_max_path_size() - 40 < strlen(gitdirenv))
die(_("'$%s' too big"), GIT_DIR_ENVIRONMENT);

gitfile = (char*)read_gitfile(gitdirenv);
Expand Down

0 comments on commit 7a3a4c7

Please sign in to comment.