]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Sync with 2.20.2
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Wed, 4 Dec 2019 21:46:37 +0000 (22:46 +0100)
committerJohannes Schindelin <johannes.schindelin@gmx.de>
Fri, 6 Dec 2019 15:31:12 +0000 (16:31 +0100)
* maint-2.20: (36 commits)
  Git 2.20.2
  t7415: adjust test for dubiously-nested submodule gitdirs for v2.20.x
  Git 2.19.3
  Git 2.18.2
  Git 2.17.3
  Git 2.16.6
  test-drop-caches: use `has_dos_drive_prefix()`
  Git 2.15.4
  Git 2.14.6
  mingw: handle `subst`-ed "DOS drives"
  mingw: refuse to access paths with trailing spaces or periods
  mingw: refuse to access paths with illegal characters
  unpack-trees: let merged_entry() pass through do_add_entry()'s errors
  quote-stress-test: offer to test quoting arguments for MSYS2 sh
  t6130/t9350: prepare for stringent Win32 path validation
  quote-stress-test: allow skipping some trials
  quote-stress-test: accept arguments to test via the command-line
  tests: add a helper to stress test argument quoting
  mingw: fix quoting of arguments
  Disallow dubiously-nested submodule git directories
  ...

25 files changed:
1  2 
Documentation/git-fast-import.txt
builtin/clone.c
builtin/submodule--helper.c
compat/mingw.c
compat/mingw.h
compat/win32/path-utils.c
compat/win32/path-utils.h
config.mak.uname
connect.c
environment.c
fast-import.c
fsck.c
git-compat-util.h
git-submodule.sh
path.c
read-cache.c
submodule.c
submodule.h
t/helper/test-path-utils.c
t/t1450-fsck.sh
t/t7415-submodule-names.sh
t/t9350-fast-export.sh
transport-helper.c
tree-walk.c
unpack-trees.c

Simple merge
diff --cc builtin/clone.c
Simple merge
index b80fc4ba3d88b56436fa3f6b9a132bfe9e82b79b,f26bdace0ba9c185ddf196e7e79206cc2d25e17d..24dbd5e65c195ec4ef55fe9439c78024dd6c3d26
@@@ -1553,9 -1561,9 +1565,9 @@@ struct submodule_update_clone 
        int max_jobs;
  };
  #define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
-       SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, \
+       SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, 0, \
        NULL, NULL, NULL, \
 -      NULL, 0, 0, 0, NULL, 0, 0, 0}
 +      NULL, 0, 0, 0, NULL, 0, 0, 1}
  
  
  static void next_submodule_warn_missing(struct submodule_update_clone *suc,
diff --cc compat/mingw.c
Simple merge
diff --cc compat/mingw.h
Simple merge
index d9d3641de8574506ca1aa9fc00cf5012631a03b6,0000000000000000000000000000000000000000..ebf2f12eb666910eede5a7e04ee2ab5b0dddb0f8
mode 100644,000000..100644
--- /dev/null
@@@ -1,28 -1,0 +1,52 @@@
 +#include "../../git-compat-util.h"
 +
++int win32_has_dos_drive_prefix(const char *path)
++{
++      int i;
++
++      /*
++       * Does it start with an ASCII letter (i.e. highest bit not set),
++       * followed by a colon?
++       */
++      if (!(0x80 & (unsigned char)*path))
++              return *path && path[1] == ':' ? 2 : 0;
++
++      /*
++       * While drive letters must be letters of the English alphabet, it is
++       * possible to assign virtually _any_ Unicode character via `subst` as
++       * a drive letter to "virtual drives". Even `1`, or `ä`. Or fun stuff
++       * like this:
++       *
++       *      subst ֍: %USERPROFILE%\Desktop
++       */
++      for (i = 1; i < 4 && (0x80 & (unsigned char)path[i]); i++)
++              ; /* skip first UTF-8 character */
++      return path[i] == ':' ? i + 1 : 0;
++}
++
 +int win32_skip_dos_drive_prefix(char **path)
 +{
 +      int ret = has_dos_drive_prefix(*path);
 +      *path += ret;
 +      return ret;
 +}
 +
 +int win32_offset_1st_component(const char *path)
 +{
 +      char *pos = (char *)path;
 +
 +      /* unc paths */
 +      if (!skip_dos_drive_prefix(&pos) &&
 +                      is_dir_sep(pos[0]) && is_dir_sep(pos[1])) {
 +              /* skip server name */
 +              pos = strpbrk(pos + 2, "\\/");
 +              if (!pos)
 +                      return 0; /* Error: malformed unc path */
 +
 +              do {
 +                      pos++;
 +              } while (*pos && !is_dir_sep(*pos));
 +      }
 +
 +      return pos + is_dir_sep(*pos) - path;
 +}
index 0f70d439204fbe1336dcea51c43a38498e69de96,0000000000000000000000000000000000000000..3403681458b9db1631a962021cb5ad57845192d4
mode 100644,000000..100644
--- /dev/null
@@@ -1,20 -1,0 +1,21 @@@
- #define has_dos_drive_prefix(path) \
-       (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
++int win32_has_dos_drive_prefix(const char *path);
++#define has_dos_drive_prefix win32_has_dos_drive_prefix
++
 +int win32_skip_dos_drive_prefix(char **path);
 +#define skip_dos_drive_prefix win32_skip_dos_drive_prefix
 +static inline int win32_is_dir_sep(int c)
 +{
 +      return c == '/' || c == '\\';
 +}
 +#define is_dir_sep win32_is_dir_sep
 +static inline char *win32_find_last_dir_sep(const char *path)
 +{
 +      char *ret = NULL;
 +      for (; *path; ++path)
 +              if (is_dir_sep(*path))
 +                      ret = (char *)path;
 +      return ret;
 +}
 +#define find_last_dir_sep win32_find_last_dir_sep
 +int win32_offset_1st_component(const char *path);
 +#define offset_1st_component win32_offset_1st_component
index b37fa8424c88cae23abf02f8276e8b4f6ffef19a,85af9f9cf1081335b786ddab7907cebb37ceb66d..76d6c0043a4853fa3300f32f3fe0da4fe7a9024d
@@@ -546,10 -526,9 +545,10 @@@ ifneq (,$(findstring MINGW,$(uname_S))
        COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
        COMPAT_OBJS += compat/mingw.o compat/winansi.o \
 +              compat/win32/path-utils.o \
                compat/win32/pthread.o compat/win32/syslog.o \
                compat/win32/dirent.o
-       BASIC_CFLAGS += -DWIN32 -DPROTECT_NTFS_DEFAULT=1
+       BASIC_CFLAGS += -DWIN32
        EXTLIBS += -lws2_32
        GITLIBS += git.res
        PTHREAD_LIBS =
diff --cc connect.c
Simple merge
diff --cc environment.c
Simple merge
diff --cc fast-import.c
Simple merge
diff --cc fsck.c
Simple merge
Simple merge
Simple merge
diff --cc path.c
Simple merge
diff --cc read-cache.c
Simple merge
diff --cc submodule.c
Simple merge
diff --cc submodule.h
Simple merge
index 5d543ad21f89c76534e8efe32d6ead512dc7d0c3,e737a941d3bc1d58c768b2e2819d0759e17f83c2..409034cf4eef59363653b39cf3aae3fc37c07856
@@@ -177,14 -177,99 +177,107 @@@ static int is_dotgitmodules(const char 
        return is_hfs_dotgitmodules(path) || is_ntfs_dotgitmodules(path);
  }
  
 +static int cmp_by_st_size(const void *a, const void *b)
 +{
 +      intptr_t x = (intptr_t)((struct string_list_item *)a)->util;
 +      intptr_t y = (intptr_t)((struct string_list_item *)b)->util;
 +
 +      return x > y ? -1 : (x < y ? +1 : 0);
 +}
 +
+ /*
+  * A very simple, reproducible pseudo-random generator. Copied from
+  * `test-genrandom.c`.
+  */
+ static uint64_t my_random_value = 1234;
+ static uint64_t my_random(void)
+ {
+       my_random_value = my_random_value * 1103515245 + 12345;
+       return my_random_value;
+ }
+ /*
+  * A fast approximation of the square root, without requiring math.h.
+  *
+  * It uses Newton's method to approximate the solution of 0 = x^2 - value.
+  */
+ static double my_sqrt(double value)
+ {
+       const double epsilon = 1e-6;
+       double x = value;
+       if (value == 0)
+               return 0;
+       for (;;) {
+               double delta = (value / x - x) / 2;
+               if (delta < epsilon && delta > -epsilon)
+                       return x + delta;
+               x += delta;
+       }
+ }
+ static int protect_ntfs_hfs_benchmark(int argc, const char **argv)
+ {
+       size_t i, j, nr, min_len = 3, max_len = 20;
+       char **names;
+       int repetitions = 15, file_mode = 0100644;
+       uint64_t begin, end;
+       double m[3][2], v[3][2];
+       uint64_t cumul;
+       double cumul2;
+       if (argc > 1 && !strcmp(argv[1], "--with-symlink-mode")) {
+               file_mode = 0120000;
+               argc--;
+               argv++;
+       }
+       nr = argc > 1 ? strtoul(argv[1], NULL, 0) : 1000000;
+       ALLOC_ARRAY(names, nr);
+       if (argc > 2) {
+               min_len = strtoul(argv[2], NULL, 0);
+               if (argc > 3)
+                       max_len = strtoul(argv[3], NULL, 0);
+               if (min_len > max_len)
+                       die("min_len > max_len");
+       }
+       for (i = 0; i < nr; i++) {
+               size_t len = min_len + (my_random() % (max_len + 1 - min_len));
+               names[i] = xmallocz(len);
+               while (len > 0)
+                       names[i][--len] = (char)(' ' + (my_random() % ('\x7f' - ' ')));
+       }
+       for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
+               for (protect_hfs = 0; protect_hfs < 2; protect_hfs++) {
+                       cumul = 0;
+                       cumul2 = 0;
+                       for (i = 0; i < repetitions; i++) {
+                               begin = getnanotime();
+                               for (j = 0; j < nr; j++)
+                                       verify_path(names[j], file_mode);
+                               end = getnanotime();
+                               printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", protect_ntfs, protect_hfs, (end-begin) / (double)1e6);
+                               cumul += end - begin;
+                               cumul2 += (end - begin) * (end - begin);
+                       }
+                       m[protect_ntfs][protect_hfs] = cumul / (double)repetitions;
+                       v[protect_ntfs][protect_hfs] = my_sqrt(cumul2 / (double)repetitions - m[protect_ntfs][protect_hfs] * m[protect_ntfs][protect_hfs]);
+                       printf("mean: %lfms, stddev: %lfms\n", m[protect_ntfs][protect_hfs] / (double)1e6, v[protect_ntfs][protect_hfs] / (double)1e6);
+               }
+       for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++)
+               for (protect_hfs = 0; protect_hfs < 2; protect_hfs++)
+                       printf("ntfs=%d/hfs=%d: %lf%% slower\n", protect_ntfs, protect_hfs, (m[protect_ntfs][protect_hfs] - m[0][0]) * 100 / m[0][0]);
+       return 0;
+ }
  int cmd__path_utils(int argc, const char **argv)
  {
        if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
                return !!res;
        }
  
 +      if (argc > 2 && !strcmp(argv[1], "file-size")) {
 +              int res = 0, i;
 +              struct stat st;
 +
 +              for (i = 2; i < argc; i++)
 +                      if (stat(argv[i], &st))
 +                              res = error_errno("Cannot stat '%s'", argv[i]);
 +                      else
 +                              printf("%"PRIuMAX"\n", (uintmax_t)st.st_size);
 +              return !!res;
 +      }
 +
 +      if (argc == 4 && !strcmp(argv[1], "skip-n-bytes")) {
 +              int fd = open(argv[2], O_RDONLY), offset = atoi(argv[3]);
 +              char buffer[65536];
 +
 +              if (fd < 0)
 +                      die_errno("could not open '%s'", argv[2]);
 +              if (lseek(fd, offset, SEEK_SET) < 0)
 +                      die_errno("could not skip %d bytes", offset);
 +              for (;;) {
 +                      ssize_t count = read(fd, buffer, sizeof(buffer));
 +                      if (count < 0)
 +                              die_errno("could not read '%s'", argv[2]);
 +                      if (!count)
 +                              break;
 +                      if (write(1, buffer, count) < 0)
 +                              die_errno("could not write to stdout");
 +              }
 +              close(fd);
 +              return 0;
 +      }
 +
 +      if (argc > 5 && !strcmp(argv[1], "slice-tests")) {
 +              int res = 0;
 +              long offset, stride, i;
 +              struct string_list list = STRING_LIST_INIT_NODUP;
 +              struct stat st;
 +
 +              offset = strtol(argv[2], NULL, 10);
 +              stride = strtol(argv[3], NULL, 10);
 +              if (stride < 1)
 +                      stride = 1;
 +              for (i = 4; i < argc; i++)
 +                      if (stat(argv[i], &st))
 +                              res = error_errno("Cannot stat '%s'", argv[i]);
 +                      else
 +                              string_list_append(&list, argv[i])->util =
 +                                      (void *)(intptr_t)st.st_size;
 +              QSORT(list.items, list.nr, cmp_by_st_size);
 +              for (i = offset; i < list.nr; i+= stride)
 +                      printf("%s\n", list.items[i].string);
 +
 +              return !!res;
 +      }
 +
+       if (argc > 1 && !strcmp(argv[1], "protect_ntfs_hfs"))
+               return !!protect_ntfs_hfs_benchmark(argc - 1, argv + 1);
+       if (argc > 1 && !strcmp(argv[1], "is_valid_path")) {
+               int res = 0, expect = 1, i;
+               for (i = 2; i < argc; i++)
+                       if (!strcmp("--not", argv[i]))
+                               expect = 0;
+                       else if (expect != is_valid_path(argv[i]))
+                               res = error("'%s' is%s a valid path",
+                                           argv[i], expect ? " not" : "");
+                       else
+                               fprintf(stderr,
+                                       "'%s' is%s a valid path\n",
+                                       argv[i], expect ? "" : " not");
+               return !!res;
+       }
        fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
                argv[1] ? argv[1] : "(there was none)");
        return 1;
diff --cc t/t1450-fsck.sh
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc tree-walk.c
Simple merge
diff --cc unpack-trees.c
Simple merge